All of lore.kernel.org
 help / color / mirror / Atom feed
* [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

* [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 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

* 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.