Commit edaf9428 authored by Paolo Valente's avatar Paolo Valente Committed by Jens Axboe

block, bfq: boost throughput with flash-based non-queueing devices

When a queue associated with a process remains empty, there are cases
where throughput gets boosted if the device is idled to await the
arrival of a new I/O request for that queue. Currently, BFQ assumes
that one of these cases is when the device has no internal queueing
(regardless of the properties of the I/O being served). Unfortunately,
this condition has proved to be too general. So, this commit refines it
as "the device has no internal queueing and is rotational".

This refinement provides a significant throughput boost with random
I/O, on flash-based storage without internal queueing. For example, on
a HiKey board, throughput increases by up to 125%, growing, e.g., from
6.9MB/s to 15.6MB/s with two or three random readers in parallel.
Signed-off-by: default avatarPaolo Valente <paolo.valente@linaro.org>
Signed-off-by: default avatarLuca Miccio <lucmiccio@gmail.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent d5be3fef
...@@ -3114,7 +3114,10 @@ static bool bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq) ...@@ -3114,7 +3114,10 @@ static bool bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq)
static bool bfq_bfqq_may_idle(struct bfq_queue *bfqq) static bool bfq_bfqq_may_idle(struct bfq_queue *bfqq)
{ {
struct bfq_data *bfqd = bfqq->bfqd; struct bfq_data *bfqd = bfqq->bfqd;
bool idling_boosts_thr, idling_boosts_thr_without_issues, bool rot_without_queueing =
!blk_queue_nonrot(bfqd->queue) && !bfqd->hw_tag,
bfqq_sequential_and_IO_bound,
idling_boosts_thr, idling_boosts_thr_without_issues,
idling_needed_for_service_guarantees, idling_needed_for_service_guarantees,
asymmetric_scenario; asymmetric_scenario;
...@@ -3133,28 +3136,34 @@ static bool bfq_bfqq_may_idle(struct bfq_queue *bfqq) ...@@ -3133,28 +3136,34 @@ static bool bfq_bfqq_may_idle(struct bfq_queue *bfqq)
bfq_class_idle(bfqq)) bfq_class_idle(bfqq))
return false; return false;
bfqq_sequential_and_IO_bound = !BFQQ_SEEKY(bfqq) &&
bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_has_short_ttime(bfqq);
/* /*
* The next variable takes into account the cases where idling * The next variable takes into account the cases where idling
* boosts the throughput. * boosts the throughput.
* *
* The value of the variable is computed considering, first, that * The value of the variable is computed considering, first, that
* idling is virtually always beneficial for the throughput if: * idling is virtually always beneficial for the throughput if:
* (a) the device is not NCQ-capable, or * (a) the device is not NCQ-capable and rotational, or
* (b) regardless of the presence of NCQ, the device is rotational * (b) regardless of the presence of NCQ, the device is rotational and
* and the request pattern for bfqq is I/O-bound and sequential. * the request pattern for bfqq is I/O-bound and sequential, or
* (c) regardless of whether it is rotational, the device is
* not NCQ-capable and the request pattern for bfqq is
* I/O-bound and sequential.
* *
* Secondly, and in contrast to the above item (b), idling an * Secondly, and in contrast to the above item (b), idling an
* NCQ-capable flash-based device would not boost the * NCQ-capable flash-based device would not boost the
* throughput even with sequential I/O; rather it would lower * throughput even with sequential I/O; rather it would lower
* the throughput in proportion to how fast the device * the throughput in proportion to how fast the device
* is. Accordingly, the next variable is true if any of the * is. Accordingly, the next variable is true if any of the
* above conditions (a) and (b) is true, and, in particular, * above conditions (a), (b) or (c) is true, and, in
* happens to be false if bfqd is an NCQ-capable flash-based * particular, happens to be false if bfqd is an NCQ-capable
* device. * flash-based device.
*/ */
idling_boosts_thr = !bfqd->hw_tag || idling_boosts_thr = rot_without_queueing ||
(!blk_queue_nonrot(bfqd->queue) && bfq_bfqq_IO_bound(bfqq) && ((!blk_queue_nonrot(bfqd->queue) || !bfqd->hw_tag) &&
bfq_bfqq_has_short_ttime(bfqq)); bfqq_sequential_and_IO_bound);
/* /*
* The value of the next variable, * The value of the next variable,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment