[HD2 Android SD Development] 3dak:
FYI: http://algo.ing.unimo.it/people/paolo/disk_sched/description.php

This is a short description of the BFQ's propoerties and of how it works ; you can find all the details about the algorithm in this technical report (full version of the paper we published Transactions on Computers, see the list of pubblications in my home for citation). There you can also find a detailed comparison against other production and research schedulers. A shorter comparison is here.

Properties

BFQ (Budget Fair Queueing) is a Proportional Share, or equivalently Fair Queueing, disk scheduler that allows each process/thread to be assigned a fraction of the disk throughput. It has the following characteristics.

◦ It distributes the disk throughput to disk-bound proceses as desired, even if it fluctuates, independently of the disk parameters and with any workload. Providing this sector-domain fairness to processes issuing random requests would easily cause the disk throughput to drop on one hand, and cause other processes to experience very high latencies on the other hand. To face this problem, for processes issuing random requests, BFQ switches to time-domain fairness, in which it is the disk time to be fairly distributed (basically the scheme of CFQ).

◦ According to our results, BFQ achieves up to 30% higher aggregate disk throughput than CFQ with most of the workloads considered, or the same throughput with the others.

◦BFQ guarantees to each disk request a tight delay with respect to the completion time that the requests would enjoy in an ideal (unfeasible) perfectly-fair system.

◦ BFQ exports a low_latency tunable. If enabled (currently the default), BFQ executes a special heuristics that automatically gives to interactive and soft real-time applications more than their fair share of the disk throughput, to reduce their latency. According to our results, for desktop or handheld usage, the system becomes virtually as responsive as if the disk was idle, whatever the actual disk load is. Soft real-time applications enjoy up to 3-time lower latencies than under CFQ.

◦ Low-latency guarantees are preserved also in presence of NCQ.

Internals

BFQ is based on CFQ code, but it implements a more accurate scheduling policy. In case you already know CFQ: in brief, differently from CFQ, BFQ does not grant the disk to each process for a fixed time-slice, but until the process exhausts a previously assigned budget, measured in number of sectors. Budgets are scheduled with an internal budget scheduler, B-WF2Q+, a modified version of the WF2Q+ packet scheduler.

More in detail, in BFQ, as in CFQ, synchronous requests are collected in per-task queues, and asynchronous requests are collected in per-device (or, in case of hierarchical scheduling, per group) queues. When a new queue is created, it is assigned a budget, measured in number of sectors, to use when the queue itself is granted access to the disk. BFQ exclusively serves one queue at a time. When the underlying device driver asks for the next request to serve, BFQ selects the first request from the queue under service in C-LOOK order and returns it to the driver. The budget of the queue is decremented by the size of the request. As in CFQ, if a sync queue has no more requests to serve, but it has some budget left, the scheduler idles (i.e., it tells to the device driver that it has no requests to serve even if there are other backlogged queues) for a short period, waiting for a new request from the task associated to the queue. The queue under service goes on being served until one of the following conditions is met:

◦the idling timer expires while BFQ is idling to wait for the arrival of the next request from the task associated to the queue

◦the queue is spending too much time to consume its budget (budget timeout, see the timeout_* parameters below), or

◦the queue exhausts its budget, or

◦the queue is not sync and has no more requests to serve.

When the queue is deselected, it is assigned a new budget, computed as a function of which of the above events occurred. The next queue to serve is selected with B-WF2Q+, a modified version of the WF2Q+ packet scheduler. B-WF2Q+ schedules backlogged queues as a function of: their budgets, their weights and the service they have already received.

Working in the service domain and not in the time domain is waht allows BFQ to distribute the disk throughput as desired, unconditionally and even if it fluctuates. In addition, the accurate service distribution of the internal B-WF2Q+ scheduler, guarantees tight delays with respect to the completion times that the requests would enjoy in an ideal perfectly-fair system.

The idea for reducing the latency for interactive and soft real-time processes (when low_latency is enabled) is just raising the weight of the associated queues. More details can be found here. An important point is that such an heuristics allows interactive and soft reeal-time queues to steal more throughput than their fair share to other queues. If the resulting loss of fairness is undesired (e.g., in a server system), it is certainly better to switch low_latency off.

When hierarchical scheduling is enabled, queues are collected in a tree of groups, and there is a distinct B-WFQ2+ scheduler on each non-leaf node. Leaf nodes are request queues as in the non-hierarchical case.

BFQ supports ioprio classes at each hierarchy level, enforcing a strict priority ordering among classes. This means that idle queues/groups are served only if there are no best effort queues/group in the same scheduler, and best effort queues/groups are served only if there are no real-time queues/groups.