All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] block: remove plug based merging
@ 2021-10-12 18:12 Jens Axboe
  2021-10-14  5:20 ` Christoph Hellwig
  0 siblings, 1 reply; 3+ messages in thread
From: Jens Axboe @ 2021-10-12 18:12 UTC (permalink / raw)
  To: linux-block

It's expensive to browse the whole plug list for merge opportunities at
the IOPS rates that modern storage can do. For sequential IO, the one-hit
cached merge should suffice on fast drives, and for rotational storage the
IO scheduler will do a more exhaustive lookup based merge anyway.

Just remove the plug based O(N) traversal merging.

Signed-off-by: Jens Axboe <axboe@kernel.dk>

---

diff --git a/block/blk-merge.c b/block/blk-merge.c
index 762da71f9fde..e10f49decd06 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -1043,62 +1043,6 @@ static enum bio_merge_status blk_attempt_bio_merge(struct request_queue *q,
 	return BIO_MERGE_FAILED;
 }
 
-/**
- * blk_attempt_plug_merge - try to merge with %current's plugged list
- * @q: request_queue new bio is being queued at
- * @bio: new bio being queued
- * @nr_segs: number of segments in @bio
- * @same_queue_rq: pointer to &struct request that gets filled in when
- * another request associated with @q is found on the plug list
- * (optional, may be %NULL)
- *
- * Determine whether @bio being queued on @q can be merged with a request
- * on %current's plugged list.  Returns %true if merge was successful,
- * otherwise %false.
- *
- * Plugging coalesces IOs from the same issuer for the same purpose without
- * going through @q->queue_lock.  As such it's more of an issuing mechanism
- * than scheduling, and the request, while may have elvpriv data, is not
- * added on the elevator at this point.  In addition, we don't have
- * reliable access to the elevator outside queue lock.  Only check basic
- * merging parameters without querying the elevator.
- *
- * Caller must ensure !blk_queue_nomerges(q) beforehand.
- */
-bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
-		unsigned int nr_segs, struct request **same_queue_rq)
-{
-	struct blk_plug *plug;
-	struct request *rq;
-	struct list_head *plug_list;
-
-	plug = blk_mq_plug(q, bio);
-	if (!plug)
-		return false;
-
-	plug_list = &plug->mq_list;
-
-	list_for_each_entry_reverse(rq, plug_list, queuelist) {
-		if (rq->q == q && same_queue_rq) {
-			/*
-			 * Only blk-mq multiple hardware queues case checks the
-			 * rq in the same queue, there should be only one such
-			 * rq in a queue
-			 **/
-			*same_queue_rq = rq;
-		}
-
-		if (rq->q != q)
-			continue;
-
-		if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) ==
-		    BIO_MERGE_OK)
-			return true;
-	}
-
-	return false;
-}
-
 /*
  * Iterate list of requests and see if we can merge this bio with any
  * of them.
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 5777064f1174..4c5b34787bbf 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -2323,10 +2323,6 @@ void blk_mq_submit_bio(struct bio *bio)
 	if (!bio_integrity_prep(bio))
 		goto queue_exit;
 
-	if (!is_flush_fua && !blk_queue_nomerges(q) &&
-	    blk_attempt_plug_merge(q, bio, nr_segs, &same_queue_rq))
-		goto queue_exit;
-
 	if (blk_mq_sched_bio_merge(q, bio, nr_segs))
 		goto queue_exit;
 
diff --git a/block/blk.h b/block/blk.h
index fa23338449ed..0afee3e6a7c1 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -214,8 +214,6 @@ static inline void blk_integrity_del(struct gendisk *disk)
 unsigned long blk_rq_timeout(unsigned long timeout);
 void blk_add_timer(struct request *req);
 
-bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
-		unsigned int nr_segs, struct request **same_queue_rq);
 bool blk_bio_list_merge(struct request_queue *q, struct list_head *list,
 			struct bio *bio, unsigned int nr_segs);
 
-- 
Jens Axboe


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] block: remove plug based merging
  2021-10-12 18:12 [PATCH] block: remove plug based merging Jens Axboe
@ 2021-10-14  5:20 ` Christoph Hellwig
  2021-10-14 12:50   ` Jens Axboe
  0 siblings, 1 reply; 3+ messages in thread
From: Christoph Hellwig @ 2021-10-14  5:20 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

On Tue, Oct 12, 2021 at 12:12:39PM -0600, Jens Axboe wrote:
> It's expensive to browse the whole plug list for merge opportunities at
> the IOPS rates that modern storage can do. For sequential IO, the one-hit
> cached merge should suffice on fast drives, and for rotational storage the
> IO scheduler will do a more exhaustive lookup based merge anyway.

I don't really want to argue, but maybe some actual measurements to
support the above claims would be useful in the commit log?

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] block: remove plug based merging
  2021-10-14  5:20 ` Christoph Hellwig
@ 2021-10-14 12:50   ` Jens Axboe
  0 siblings, 0 replies; 3+ messages in thread
From: Jens Axboe @ 2021-10-14 12:50 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-block, Ming Lei

On 10/13/21 11:20 PM, Christoph Hellwig wrote:
> On Tue, Oct 12, 2021 at 12:12:39PM -0600, Jens Axboe wrote:
>> It's expensive to browse the whole plug list for merge opportunities at
>> the IOPS rates that modern storage can do. For sequential IO, the one-hit
>> cached merge should suffice on fast drives, and for rotational storage the
>> IO scheduler will do a more exhaustive lookup based merge anyway.
> 
> I don't really want to argue, but maybe some actual measurements to
> support the above claims would be useful in the commit log?

Sure, I do need to pad the commit messages a bit. One example - running
an IOPS bound worload caps out at ~5.6M IOPS and if you check the profile
this is top of the list:

  Overhead  Command   Shared Object     Symbol                                         
+   20.89%  io_uring  [kernel.vmlinux]  [k] blk_attempt_plug_merge
+    4.98%  io_uring  [kernel.vmlinux]  [k] io_submit_sqes
+    4.78%  io_uring  [kernel.vmlinux]  [k] blkdev_direct_IO
+    4.61%  io_uring  [kernel.vmlinux]  [k] blk_mq_submit_bio
+    3.67%  io_uring  [nvme]            [k] nvme_queue_rq

Disabling merging or applying the patch, we run at ~7.4M IOPS instead.
That's about a 33% improvement from killing a silly merge loop that
isn't even marked as an expensive merge.

I'll rework the patch, we can probably retain it is a last-insert kind
of merge point. But browsing the whole plug list for a merge candidate
is stupidity, regardless of the class of workload and storage.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-10-14 12:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-12 18:12 [PATCH] block: remove plug based merging Jens Axboe
2021-10-14  5:20 ` Christoph Hellwig
2021-10-14 12:50   ` 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.