* [PATCH 0/2] optimise bvec/bio iteration @ 2020-11-24 17:58 Pavel Begunkov 2020-11-24 17:58 ` [PATCH 1/2] block: optimise for_each_bvec() advance Pavel Begunkov ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Pavel Begunkov @ 2020-11-24 17:58 UTC (permalink / raw) To: Jens Axboe, linux-block; +Cc: Ming Lei, Christoph Hellwig This adds simpler versions of bvec_iter_advance() and bio_advance_iter() (i.e. *_single()), that are faster but work with the restriction that @bytes shouldn't be more than available in the current bvec segment. That covers most of bvec/bio iteration/foreach, that are massively inlined, and thus also nicely shrinks binary. Others non core-block users might be updated on case by case basis (if applicable) after the change is merged. Pavel Begunkov (2): block: optimise for_each_bvec() advance bio: optimise bvec iteration block/bio.c | 4 ++-- include/linux/bio.h | 17 +++++++++++++++-- include/linux/bvec.h | 20 +++++++++++++++----- 3 files changed, 32 insertions(+), 9 deletions(-) -- 2.24.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] block: optimise for_each_bvec() advance 2020-11-24 17:58 [PATCH 0/2] optimise bvec/bio iteration Pavel Begunkov @ 2020-11-24 17:58 ` Pavel Begunkov 2020-11-26 10:00 ` Christoph Hellwig 2020-11-24 17:58 ` [PATCH 2/2] bio: optimise bvec iteration Pavel Begunkov 2020-12-02 16:47 ` [PATCH 0/2] optimise bvec/bio iteration Jens Axboe 2 siblings, 1 reply; 9+ messages in thread From: Pavel Begunkov @ 2020-11-24 17:58 UTC (permalink / raw) To: Jens Axboe, linux-block; +Cc: Ming Lei, Christoph Hellwig Because of how for_each_bvec() works it never advances across multiple entries at a time, so bvec_iter_advance() is an overkill. Add specialised bvec_iter_advance_single() that is faster. It also handles zero-len bvecs, so can kill bvec_iter_skip_zero_bvec(). text data bss dec hex filename before: 23977 805 0 24782 60ce lib/iov_iter.o before, bvec_iter_advance() w/o WARN_ONCE() 22886 600 0 23486 5bbe ./lib/iov_iter.o after: 21862 600 0 22462 57be lib/iov_iter.o Reviewed-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> --- include/linux/bvec.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/include/linux/bvec.h b/include/linux/bvec.h index 2efec10bf792..ff832e698efb 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h @@ -121,18 +121,28 @@ static inline bool bvec_iter_advance(const struct bio_vec *bv, return true; } -static inline void bvec_iter_skip_zero_bvec(struct bvec_iter *iter) +/* + * A simpler version of bvec_iter_advance(), @bytes should not span + * across multiple bvec entries, i.e. bytes <= bv[i->bi_idx].bv_len + */ +static inline void bvec_iter_advance_single(const struct bio_vec *bv, + struct bvec_iter *iter, unsigned int bytes) { - iter->bi_bvec_done = 0; - iter->bi_idx++; + unsigned int done = iter->bi_bvec_done + bytes; + + if (done == bv[iter->bi_idx].bv_len) { + done = 0; + iter->bi_idx++; + } + iter->bi_bvec_done = done; + iter->bi_size -= bytes; } #define for_each_bvec(bvl, bio_vec, iter, start) \ for (iter = (start); \ (iter).bi_size && \ ((bvl = bvec_iter_bvec((bio_vec), (iter))), 1); \ - (bvl).bv_len ? (void)bvec_iter_advance((bio_vec), &(iter), \ - (bvl).bv_len) : bvec_iter_skip_zero_bvec(&(iter))) + bvec_iter_advance_single((bio_vec), &(iter), (bvl).bv_len)) /* for iterating one bio from start to end */ #define BVEC_ITER_ALL_INIT (struct bvec_iter) \ -- 2.24.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] block: optimise for_each_bvec() advance 2020-11-24 17:58 ` [PATCH 1/2] block: optimise for_each_bvec() advance Pavel Begunkov @ 2020-11-26 10:00 ` Christoph Hellwig 0 siblings, 0 replies; 9+ messages in thread From: Christoph Hellwig @ 2020-11-26 10:00 UTC (permalink / raw) To: Pavel Begunkov; +Cc: Jens Axboe, linux-block, Ming Lei, Christoph Hellwig On Tue, Nov 24, 2020 at 05:58:12PM +0000, Pavel Begunkov wrote: > Because of how for_each_bvec() works it never advances across multiple > entries at a time, so bvec_iter_advance() is an overkill. Add > specialised bvec_iter_advance_single() that is faster. It also handles > zero-len bvecs, so can kill bvec_iter_skip_zero_bvec(). > > text data bss dec hex filename > before: > 23977 805 0 24782 60ce lib/iov_iter.o > before, bvec_iter_advance() w/o WARN_ONCE() > 22886 600 0 23486 5bbe ./lib/iov_iter.o > after: > 21862 600 0 22462 57be lib/iov_iter.o > > Reviewed-by: Ming Lei <ming.lei@redhat.com> > Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Looks good, Reviewed-by: Christoph Hellwig <hch@lst.de> ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] bio: optimise bvec iteration 2020-11-24 17:58 [PATCH 0/2] optimise bvec/bio iteration Pavel Begunkov 2020-11-24 17:58 ` [PATCH 1/2] block: optimise for_each_bvec() advance Pavel Begunkov @ 2020-11-24 17:58 ` Pavel Begunkov 2020-11-26 10:02 ` Christoph Hellwig 2020-12-02 14:56 ` Christoph Hellwig 2020-12-02 16:47 ` [PATCH 0/2] optimise bvec/bio iteration Jens Axboe 2 siblings, 2 replies; 9+ messages in thread From: Pavel Begunkov @ 2020-11-24 17:58 UTC (permalink / raw) To: Jens Axboe, linux-block; +Cc: Ming Lei, Christoph Hellwig __bio_for_each_bvec(), __bio_for_each_segment() and bio_copy_data_iter() fall under conditions of bvec_iter_advance_single(), which is a faster and slimmer version of bvec_iter_advance(). Add bio_advance_iter_single() and convert them. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> --- block/bio.c | 4 ++-- include/linux/bio.h | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/block/bio.c b/block/bio.c index fa01bef35bb1..8e718920457a 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1212,8 +1212,8 @@ void bio_copy_data_iter(struct bio *dst, struct bvec_iter *dst_iter, flush_dcache_page(dst_bv.bv_page); - bio_advance_iter(src, src_iter, bytes); - bio_advance_iter(dst, dst_iter, bytes); + bio_advance_iter_single(src, src_iter, bytes); + bio_advance_iter_single(dst, dst_iter, bytes); } } EXPORT_SYMBOL(bio_copy_data_iter); diff --git a/include/linux/bio.h b/include/linux/bio.h index c6d765382926..d55d53c49ae4 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -148,11 +148,24 @@ static inline void bio_advance_iter(const struct bio *bio, /* TODO: It is reasonable to complete bio with error here. */ } +/* @bytes should be less or equal to bvec[i->bi_idx].bv_len */ +static inline void bio_advance_iter_single(const struct bio *bio, + struct bvec_iter *iter, + unsigned int bytes) +{ + iter->bi_sector += bytes >> 9; + + if (bio_no_advance_iter(bio)) + iter->bi_size -= bytes; + else + bvec_iter_advance_single(bio->bi_io_vec, iter, bytes); +} + #define __bio_for_each_segment(bvl, bio, iter, start) \ for (iter = (start); \ (iter).bi_size && \ ((bvl = bio_iter_iovec((bio), (iter))), 1); \ - bio_advance_iter((bio), &(iter), (bvl).bv_len)) + bio_advance_iter_single((bio), &(iter), (bvl).bv_len)) #define bio_for_each_segment(bvl, bio, iter) \ __bio_for_each_segment(bvl, bio, iter, (bio)->bi_iter) @@ -161,7 +174,7 @@ static inline void bio_advance_iter(const struct bio *bio, for (iter = (start); \ (iter).bi_size && \ ((bvl = mp_bvec_iter_bvec((bio)->bi_io_vec, (iter))), 1); \ - bio_advance_iter((bio), &(iter), (bvl).bv_len)) + bio_advance_iter_single((bio), &(iter), (bvl).bv_len)) /* iterate over multi-page bvec */ #define bio_for_each_bvec(bvl, bio, iter) \ -- 2.24.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] bio: optimise bvec iteration 2020-11-24 17:58 ` [PATCH 2/2] bio: optimise bvec iteration Pavel Begunkov @ 2020-11-26 10:02 ` Christoph Hellwig 2020-11-26 12:32 ` Pavel Begunkov 2020-12-02 14:56 ` Christoph Hellwig 1 sibling, 1 reply; 9+ messages in thread From: Christoph Hellwig @ 2020-11-26 10:02 UTC (permalink / raw) To: Pavel Begunkov; +Cc: Jens Axboe, linux-block, Ming Lei, Christoph Hellwig On Tue, Nov 24, 2020 at 05:58:13PM +0000, Pavel Begunkov wrote: > __bio_for_each_bvec(), __bio_for_each_segment() and bio_copy_data_iter() > fall under conditions of bvec_iter_advance_single(), which is a faster > and slimmer version of bvec_iter_advance(). Add > bio_advance_iter_single() and convert them. Are you sure about bio_advance_iter()? That API looks like it might not always be limited to a single segment, and might at least need a WARN_ON_ONCE to make sure it is not abused. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] bio: optimise bvec iteration 2020-11-26 10:02 ` Christoph Hellwig @ 2020-11-26 12:32 ` Pavel Begunkov 2020-12-02 13:50 ` Pavel Begunkov 0 siblings, 1 reply; 9+ messages in thread From: Pavel Begunkov @ 2020-11-26 12:32 UTC (permalink / raw) To: Christoph Hellwig; +Cc: Jens Axboe, linux-block, Ming Lei On 26/11/2020 10:02, Christoph Hellwig wrote: > On Tue, Nov 24, 2020 at 05:58:13PM +0000, Pavel Begunkov wrote: >> __bio_for_each_bvec(), __bio_for_each_segment() and bio_copy_data_iter() >> fall under conditions of bvec_iter_advance_single(), which is a faster >> and slimmer version of bvec_iter_advance(). Add >> bio_advance_iter_single() and convert them. > > Are you sure about bio_advance_iter()? That API looks like it might Both those listed bio_for_each*() pass bvl.bv_len, which is truncated to current segment by bio_iter_iovec() (i.e. bvec_iter_bvec) or mp_bvec_iter_bvec(). And just to note that I didn't change bio_advance_iter() but added a new function. There is always space for stupid mistakes, but I'm sure. What makes you to think opposite? I may have missed it. > not always be limited to a single segment, and might at least need a > WARN_ON_ONCE to make sure it is not abused. I thought twice about converting other places as you commented before, and it looks saner to not do that exactly for that reason. I prefer to leave *_single() versions for rare but high impact cases like for_each()s. And as it's contained I decided to not add overhead on WARN_ONCE(), e.g. with inlining and w/o string dedup it grows .data section much. -- Pavel Begunkov ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] bio: optimise bvec iteration 2020-11-26 12:32 ` Pavel Begunkov @ 2020-12-02 13:50 ` Pavel Begunkov 0 siblings, 0 replies; 9+ messages in thread From: Pavel Begunkov @ 2020-12-02 13:50 UTC (permalink / raw) To: Christoph Hellwig; +Cc: Jens Axboe, linux-block, Ming Lei On 26/11/2020 12:32, Pavel Begunkov wrote: > On 26/11/2020 10:02, Christoph Hellwig wrote: >> On Tue, Nov 24, 2020 at 05:58:13PM +0000, Pavel Begunkov wrote: >>> __bio_for_each_bvec(), __bio_for_each_segment() and bio_copy_data_iter() >>> fall under conditions of bvec_iter_advance_single(), which is a faster >>> and slimmer version of bvec_iter_advance(). Add >>> bio_advance_iter_single() and convert them. >> >> Are you sure about bio_advance_iter()? That API looks like it might > > Both those listed bio_for_each*() pass bvl.bv_len, which is truncated to > current segment by bio_iter_iovec() (i.e. bvec_iter_bvec) or > mp_bvec_iter_bvec(). > > And just to note that I didn't change bio_advance_iter() but added a > new function. > There is always space for stupid mistakes, but I'm sure. What makes you > to think opposite? I may have missed it. Christoph, any doubts left? >> not always be limited to a single segment, and might at least need a >> WARN_ON_ONCE to make sure it is not abused. > > I thought twice about converting other places as you commented before, > and it looks saner to not do that exactly for that reason. I prefer > to leave *_single() versions for rare but high impact cases like > for_each()s. > And as it's contained I decided to not add overhead on WARN_ONCE(), > e.g. with inlining and w/o string dedup it grows .data section much. > -- Pavel Begunkov ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] bio: optimise bvec iteration 2020-11-24 17:58 ` [PATCH 2/2] bio: optimise bvec iteration Pavel Begunkov 2020-11-26 10:02 ` Christoph Hellwig @ 2020-12-02 14:56 ` Christoph Hellwig 1 sibling, 0 replies; 9+ messages in thread From: Christoph Hellwig @ 2020-12-02 14:56 UTC (permalink / raw) To: Pavel Begunkov; +Cc: Jens Axboe, linux-block, Ming Lei, Christoph Hellwig On Tue, Nov 24, 2020 at 05:58:13PM +0000, Pavel Begunkov wrote: > __bio_for_each_bvec(), __bio_for_each_segment() and bio_copy_data_iter() > fall under conditions of bvec_iter_advance_single(), which is a faster > and slimmer version of bvec_iter_advance(). Add > bio_advance_iter_single() and convert them. > > Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Looks good, Reviewed-by: Christoph Hellwig <hch@lst.de> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/2] optimise bvec/bio iteration 2020-11-24 17:58 [PATCH 0/2] optimise bvec/bio iteration Pavel Begunkov 2020-11-24 17:58 ` [PATCH 1/2] block: optimise for_each_bvec() advance Pavel Begunkov 2020-11-24 17:58 ` [PATCH 2/2] bio: optimise bvec iteration Pavel Begunkov @ 2020-12-02 16:47 ` Jens Axboe 2 siblings, 0 replies; 9+ messages in thread From: Jens Axboe @ 2020-12-02 16:47 UTC (permalink / raw) To: Pavel Begunkov, linux-block; +Cc: Ming Lei, Christoph Hellwig On 11/24/20 10:58 AM, Pavel Begunkov wrote: > This adds simpler versions of bvec_iter_advance() and bio_advance_iter() > (i.e. *_single()), that are faster but work with the restriction that > @bytes shouldn't be more than available in the current bvec segment. > > That covers most of bvec/bio iteration/foreach, that are massively > inlined, and thus also nicely shrinks binary. > > Others non core-block users might be updated on case by case basis > (if applicable) after the change is merged. Applied, thanks. -- Jens Axboe ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-12-02 16:48 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-11-24 17:58 [PATCH 0/2] optimise bvec/bio iteration Pavel Begunkov 2020-11-24 17:58 ` [PATCH 1/2] block: optimise for_each_bvec() advance Pavel Begunkov 2020-11-26 10:00 ` Christoph Hellwig 2020-11-24 17:58 ` [PATCH 2/2] bio: optimise bvec iteration Pavel Begunkov 2020-11-26 10:02 ` Christoph Hellwig 2020-11-26 12:32 ` Pavel Begunkov 2020-12-02 13:50 ` Pavel Begunkov 2020-12-02 14:56 ` Christoph Hellwig 2020-12-02 16:47 ` [PATCH 0/2] optimise bvec/bio iteration Jens Axboe
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).