← Documents Documentation/block/bfq-iosched.rst GitHub 원문 ↗

Linux 6.18.37 · Block

BFQ (Budget Fair Queueing)

BFQ의 latency·throughput 정책, budget algorithm, tunable과 cgroup interface를 설명합니다.

Source pathDocumentation/block/bfq-iosched.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

bfq-iosched.rst:1-606

BFQ는 queue weight에 비례해 실제 device bandwidth를 분배하면서 interactive·soft real-time workload의 latency를 낮추는 proportional-share I/O scheduler입니다.

강한 service guarantee에는 idling과 request serialization 비용이 따릅니다. `slice_idle`, `strict_guarantees`, `low_latency`, `timeout_sync`, `max_budget`을 storage 특성과 목표에 맞게 조정해야 합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ==========================
2 BFQ (Budget Fair Queueing)
3 ==========================
4
5 BFQ is a proportional-share I/O scheduler, with some extra
6 low-latency capabilities. In addition to cgroups support (blkio or io
7 controllers), BFQ's main features are:
8
9 - BFQ guarantees a high system and application responsiveness, and a
10 low latency for time-sensitive applications, such as audio or video
11 players;
12 - BFQ distributes bandwidth, not just time, among processes or
13 groups (switching back to time distribution when needed to keep
14 throughput high).
15
16 In its default configuration, BFQ privileges latency over
17 throughput. So, when needed for achieving a lower latency, BFQ builds
18 schedules that may lead to a lower throughput. If your main or only
19 goal, for a given device, is to achieve the maximum-possible
20 throughput at all times, then do switch off all low-latency heuristics
21 for that device, by setting low_latency to 0. See Section 3 for
22 details on how to configure BFQ for the desired tradeoff between
23 latency and throughput, or on how to maximize throughput.
24
25 As every I/O scheduler, BFQ adds some overhead to per-I/O-request
26 processing. To give an idea of this overhead, the total,
27 single-lock-protected, per-request processing time of BFQ---i.e., the
28 sum of the execution times of the request insertion, dispatch and
29 completion hooks---is, e.g., 1.9 us on an Intel Core [email protected]
30 (dated CPU for notebooks; time measured with simple code
31 instrumentation, and using the throughput-sync.sh script of the S
32 suite [1], in performance-profiling mode). To put this result into
33 context, the total, single-lock-protected, per-request execution time
34 of the lightest I/O scheduler available in blk-mq, mq-deadline, is 0.7
35 us (mq-deadline is ~800 LOC, against ~10500 LOC for BFQ).
36
37 Scheduling overhead further limits the maximum IOPS that a CPU can
38 process (already limited by the execution of the rest of the I/O
39 stack). To give an idea of the limits with BFQ, on slow or average
40 CPUs, here are, first, the limits of BFQ for three different CPUs, on,
41 respectively, an average laptop, an old desktop, and a cheap embedded
42 system, in case full hierarchical support is enabled (i.e.,
43 CONFIG_BFQ_GROUP_IOSCHED is set), but CONFIG_BFQ_CGROUP_DEBUG is not
44 set (Section 4-2):
45 - Intel i7-4850HQ: 400 KIOPS
46 - AMD A8-3850: 250 KIOPS
47 - ARM CortexTM-A53 Octa-core: 80 KIOPS
48
49 If CONFIG_BFQ_CGROUP_DEBUG is set (and of course full hierarchical
50 support is enabled), then the sustainable throughput with BFQ
51 decreases, because all blkio.bfq* statistics are created and updated
52 (Section 4-2). For BFQ, this leads to the following maximum
53 sustainable throughputs, on the same systems as above:
54 - Intel i7-4850HQ: 310 KIOPS
55 - AMD A8-3850: 200 KIOPS
56 - ARM CortexTM-A53 Octa-core: 56 KIOPS
57
58 BFQ works for multi-queue devices too.
59
60 .. The table of contents follow. Impatients can just jump to Section 3.
61
62 .. CONTENTS
63
64 1. When may BFQ be useful?
65 1-1 Personal systems
66 1-2 Server systems
67 2. How does BFQ work?
68 3. What are BFQ's tunables and how to properly configure BFQ?
69 4. BFQ group scheduling
70 4-1 Service guarantees provided
71 4-2 Interface
72
73 1. When may BFQ be useful?
74 ==========================
75
76 BFQ provides the following benefits on personal and server systems.
77
78 1-1 Personal systems
79 --------------------
80
81 Low latency for interactive applications
82 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
83
84 Regardless of the actual background workload, BFQ guarantees that, for
85 interactive tasks, the storage device is virtually as responsive as if
86 it was idle. For example, even if one or more of the following
87 background workloads are being executed:
88
89 - one or more large files are being read, written or copied,
90 - a tree of source files is being compiled,
91 - one or more virtual machines are performing I/O,
92 - a software update is in progress,
93 - indexing daemons are scanning filesystems and updating their
94 databases,
95
96 starting an application or loading a file from within an application
97 takes about the same time as if the storage device was idle. As a
98 comparison, with CFQ, NOOP or DEADLINE, and in the same conditions,
99 applications experience high latencies, or even become unresponsive
100 until the background workload terminates (also on SSDs).
101
102 Low latency for soft real-time applications
103 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
104 Also soft real-time applications, such as audio and video
105 players/streamers, enjoy a low latency and a low drop rate, regardless
106 of the background I/O workload. As a consequence, these applications
107 do not suffer from almost any glitch due to the background workload.
108
109 Higher speed for code-development tasks
110 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
111
112 If some additional workload happens to be executed in parallel, then
113 BFQ executes the I/O-related components of typical code-development
114 tasks (compilation, checkout, merge, etc.) much more quickly than CFQ,
115 NOOP or DEADLINE.
116
117 High throughput
118 ^^^^^^^^^^^^^^^
119
120 On hard disks, BFQ achieves up to 30% higher throughput than CFQ, and
121 up to 150% higher throughput than DEADLINE and NOOP, with all the
122 sequential workloads considered in our tests. With random workloads,
123 and with all the workloads on flash-based devices, BFQ achieves,
124 instead, about the same throughput as the other schedulers.
125
126 Strong fairness, bandwidth and delay guarantees
127 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
128
129 BFQ distributes the device throughput, and not just the device time,
130 among I/O-bound applications in proportion to their weights, with any
131 workload and regardless of the device parameters. From these bandwidth
132 guarantees, it is possible to compute a tight per-I/O-request delay
133 guarantees by a simple formula. If not configured for strict service
134 guarantees, BFQ switches to time-based resource sharing (only) for
135 applications that would otherwise cause a throughput loss.
136
137 1-2 Server systems
138 ------------------
139
140 Most benefits for server systems follow from the same service
141 properties as above. In particular, regardless of whether additional,
142 possibly heavy workloads are being served, BFQ guarantees:
143
144 * audio and video-streaming with zero or very low jitter and drop
145 rate;
146
147 * fast retrieval of WEB pages and embedded objects;
148
149 * real-time recording of data in live-dumping applications (e.g.,
150 packet logging);
151
152 * responsiveness in local and remote access to a server.
153
154
155 2. How does BFQ work?
156 =====================
157
158 BFQ is a proportional-share I/O scheduler, whose general structure,
159 plus a lot of code, are borrowed from CFQ.
160
161 - Each process doing I/O on a device is associated with a weight and a
162 `(bfq_)queue`.
163
164 - BFQ grants exclusive access to the device, for a while, to one queue
165 (process) at a time, and implements this service model by
166 associating every queue with a budget, measured in number of
167 sectors.
168
169 - After a queue is granted access to the device, the budget of the
170 queue is decremented, on each request dispatch, by the size of the
171 request.
172
173 - The in-service queue is expired, i.e., its service is suspended,
174 only if one of the following events occurs: 1) the queue finishes
175 its budget, 2) the queue empties, 3) a "budget timeout" fires.
176
177 - The budget timeout prevents processes doing random I/O from
178 holding the device for too long and dramatically reducing
179 throughput.
180
181 - Actually, as in CFQ, a queue associated with a process issuing
182 sync requests may not be expired immediately when it empties. In
183 contrast, BFQ may idle the device for a short time interval,
184 giving the process the chance to go on being served if it issues
185 a new request in time. Device idling typically boosts the
186 throughput on rotational devices and on non-queueing flash-based
187 devices, if processes do synchronous and sequential I/O. In
188 addition, under BFQ, device idling is also instrumental in
189 guaranteeing the desired throughput fraction to processes
190 issuing sync requests (see the description of the slice_idle
191 tunable in this document, or [1, 2], for more details).
192
193 - With respect to idling for service guarantees, if several
194 processes are competing for the device at the same time, but
195 all processes and groups have the same weight, then BFQ
196 guarantees the expected throughput distribution without ever
197 idling the device. Throughput is thus as high as possible in
198 this common scenario.
199
200 - On flash-based storage with internal queueing of commands
201 (typically NCQ), device idling happens to be always detrimental
202 to throughput. So, with these devices, BFQ performs idling
203 only when strictly needed for service guarantees, i.e., for
204 guaranteeing low latency or fairness. In these cases, overall
205 throughput may be sub-optimal. No solution currently exists to
206 provide both strong service guarantees and optimal throughput
207 on devices with internal queueing.
208
209 - If low-latency mode is enabled (default configuration), BFQ
210 executes some special heuristics to detect interactive and soft
211 real-time applications (e.g., video or audio players/streamers),
212 and to reduce their latency. The most important action taken to
213 achieve this goal is to give to the queues associated with these
214 applications more than their fair share of the device
215 throughput. For brevity, we call it just "weight-raising" the whole
216 sets of actions taken by BFQ to privilege these queues. In
217 particular, BFQ provides a milder form of weight-raising for
218 interactive applications, and a stronger form for soft real-time
219 applications.
220
221 - BFQ automatically deactivates idling for queues born in a burst of
222 queue creations. In fact, these queues are usually associated with
223 the processes of applications and services that benefit mostly
224 from a high throughput. Examples are systemd during boot, or git
225 grep.
226
227 - As CFQ, BFQ merges queues performing interleaved I/O, i.e.,
228 performing random I/O that becomes mostly sequential if
229 merged. Differently from CFQ, BFQ achieves this goal with a more
230 reactive mechanism, called Early Queue Merge (EQM). EQM is so
231 responsive in detecting interleaved I/O (cooperating processes),
232 that it enables BFQ to achieve a high throughput, by queue
233 merging, even for queues for which CFQ needs a different
234 mechanism, preemption, to get a high throughput. As such, EQM is a
235 unified mechanism to achieve a high throughput with interleaved
236 I/O.
237
238 - Queues are scheduled according to a variant of WF2Q+, named
239 B-WF2Q+, and implemented using an augmented rb-tree to preserve an
240 O(log N) overall complexity. See [2] for more details. B-WF2Q+ is
241 also ready for hierarchical scheduling, details in Section 4.
242
243 - B-WF2Q+ guarantees a tight deviation with respect to an ideal,
244 perfectly fair, and smooth service. In particular, B-WF2Q+
245 guarantees that each queue receives a fraction of the device
246 throughput proportional to its weight, even if the throughput
247 fluctuates, and regardless of: the device parameters, the current
248 workload and the budgets assigned to the queue.
249
250 - The last, budget-independence, property (although probably
251 counterintuitive in the first place) is definitely beneficial, for
252 the following reasons:
253
254 - First, with any proportional-share scheduler, the maximum
255 deviation with respect to an ideal service is proportional to
256 the maximum budget (slice) assigned to queues. As a consequence,
257 BFQ can keep this deviation tight, not only because of the
258 accurate service of B-WF2Q+, but also because BFQ *does not*
259 need to assign a larger budget to a queue to let the queue
260 receive a higher fraction of the device throughput.
261
262 - Second, BFQ is free to choose, for every process (queue), the
263 budget that best fits the needs of the process, or best
264 leverages the I/O pattern of the process. In particular, BFQ
265 updates queue budgets with a simple feedback-loop algorithm that
266 allows a high throughput to be achieved, while still providing
267 tight latency guarantees to time-sensitive applications. When
268 the in-service queue expires, this algorithm computes the next
269 budget of the queue so as to:
270
271 - Let large budgets be eventually assigned to the queues
272 associated with I/O-bound applications performing sequential
273 I/O: in fact, the longer these applications are served once
274 got access to the device, the higher the throughput is.
275
276 - Let small budgets be eventually assigned to the queues
277 associated with time-sensitive applications (which typically
278 perform sporadic and short I/O), because, the smaller the
279 budget assigned to a queue waiting for service is, the sooner
280 B-WF2Q+ will serve that queue (Subsec 3.3 in [2]).
281
282 - If several processes are competing for the device at the same time,
283 but all processes and groups have the same weight, then BFQ
284 guarantees the expected throughput distribution without ever idling
285 the device. It uses preemption instead. Throughput is then much
286 higher in this common scenario.
287
288 - ioprio classes are served in strict priority order, i.e.,
289 lower-priority queues are not served as long as there are
290 higher-priority queues. Among queues in the same class, the
291 bandwidth is distributed in proportion to the weight of each
292 queue. A very thin extra bandwidth is however guaranteed to
293 the Idle class, to prevent it from starving.
294
295
296 3. What are BFQ's tunables and how to properly configure BFQ?
297 =============================================================
298
299 Most BFQ tunables affect service guarantees (basically latency and
300 fairness) and throughput. For full details on how to choose the
301 desired tradeoff between service guarantees and throughput, see the
302 parameters slice_idle, strict_guarantees and low_latency. For details
303 on how to maximise throughput, see slice_idle, timeout_sync and
304 max_budget. The other performance-related parameters have been
305 inherited from, and have been preserved mostly for compatibility with
306 CFQ. So far, no performance improvement has been reported after
307 changing the latter parameters in BFQ.
308
309 In particular, the tunables back_seek-max, back_seek_penalty,
310 fifo_expire_async and fifo_expire_sync below are the same as in
311 CFQ. Their description is just copied from that for CFQ. Some
312 considerations in the description of slice_idle are copied from CFQ
313 too.
314
315 per-process ioprio and weight
316 -----------------------------
317
318 Unless the cgroups interface is used (see "4. BFQ group scheduling"),
319 weights can be assigned to processes only indirectly, through I/O
320 priorities, and according to the relation:
321 weight = (IOPRIO_BE_NR - ioprio) * 10.
322
323 Beware that, if low-latency is set, then BFQ automatically raises the
324 weight of the queues associated with interactive and soft real-time
325 applications. Unset this tunable if you need/want to control weights.
326
327 slice_idle
328 ----------
329
330 This parameter specifies how long BFQ should idle for the next I/O
331 request, when certain sync BFQ queues become empty. By default
332 slice_idle is a non-zero value. Idling has a double purpose: boosting
333 throughput and making sure that the desired throughput distribution is
334 respected (see the description of how BFQ works, and, if needed, the
335 papers referred there).
336
337 As for throughput, idling can be very helpful on highly seeky media
338 like single spindle SATA/SAS disks where we can cut down on overall
339 number of seeks and see improved throughput.
340
341 Setting slice_idle to 0 will remove all the idling on queues and one
342 should see an overall improved throughput on faster storage devices
343 like multiple SATA/SAS disks in hardware RAID configuration, as well
344 as flash-based storage with internal command queueing (and
345 parallelism).
346
347 So depending on storage and workload, it might be useful to set
348 slice_idle=0. In general for SATA/SAS disks and software RAID of
349 SATA/SAS disks keeping slice_idle enabled should be useful. For any
350 configurations where there are multiple spindles behind single LUN
351 (Host based hardware RAID controller or for storage arrays), or with
352 flash-based fast storage, setting slice_idle=0 might end up in better
353 throughput and acceptable latencies.
354
355 Idling is however necessary to have service guarantees enforced in
356 case of differentiated weights or differentiated I/O-request lengths.
357 To see why, suppose that a given BFQ queue A must get several I/O
358 requests served for each request served for another queue B. Idling
359 ensures that, if A makes a new I/O request slightly after becoming
360 empty, then no request of B is dispatched in the middle, and thus A
361 does not lose the possibility to get more than one request dispatched
362 before the next request of B is dispatched. Note that idling
363 guarantees the desired differentiated treatment of queues only in
364 terms of I/O-request dispatches. To guarantee that the actual service
365 order then corresponds to the dispatch order, the strict_guarantees
366 tunable must be set too.
367
368 There is an important flip side to idling: apart from the above cases
369 where it is beneficial also for throughput, idling can severely impact
370 throughput. One important case is random workload. Because of this
371 issue, BFQ tends to avoid idling as much as possible, when it is not
372 beneficial also for throughput (as detailed in Section 2). As a
373 consequence of this behavior, and of further issues described for the
374 strict_guarantees tunable, short-term service guarantees may be
375 occasionally violated. And, in some cases, these guarantees may be
376 more important than guaranteeing maximum throughput. For example, in
377 video playing/streaming, a very low drop rate may be more important
378 than maximum throughput. In these cases, consider setting the
379 strict_guarantees parameter.
380
381 slice_idle_us
382 -------------
383
384 Controls the same tuning parameter as slice_idle, but in microseconds.
385 Either tunable can be used to set idling behavior. Afterwards, the
386 other tunable will reflect the newly set value in sysfs.
387
388 strict_guarantees
389 -----------------
390
391 If this parameter is set (default: unset), then BFQ
392
393 - always performs idling when the in-service queue becomes empty;
394
395 - forces the device to serve one I/O request at a time, by dispatching a
396 new request only if there is no outstanding request.
397
398 In the presence of differentiated weights or I/O-request sizes, both
399 the above conditions are needed to guarantee that every BFQ queue
400 receives its allotted share of the bandwidth. The first condition is
401 needed for the reasons explained in the description of the slice_idle
402 tunable. The second condition is needed because all modern storage
403 devices reorder internally-queued requests, which may trivially break
404 the service guarantees enforced by the I/O scheduler.
405
406 Setting strict_guarantees may evidently affect throughput.
407
408 back_seek_max
409 -------------
410
411 This specifies, given in Kbytes, the maximum "distance" for backward seeking.
412 The distance is the amount of space from the current head location to the
413 sectors that are backward in terms of distance.
414
415 This parameter allows the scheduler to anticipate requests in the "backward"
416 direction and consider them as being the "next" if they are within this
417 distance from the current head location.
418
419 back_seek_penalty
420 -----------------
421
422 This parameter is used to compute the cost of backward seeking. If the
423 backward distance of request is just 1/back_seek_penalty from a "front"
424 request, then the seeking cost of two requests is considered equivalent.
425
426 So scheduler will not bias toward one or the other request (otherwise scheduler
427 will bias toward front request). Default value of back_seek_penalty is 2.
428
429 fifo_expire_async
430 -----------------
431
432 This parameter is used to set the timeout of asynchronous requests. Default
433 value of this is 250ms.
434
435 fifo_expire_sync
436 ----------------
437
438 This parameter is used to set the timeout of synchronous requests. Default
439 value of this is 125ms. In case to favor synchronous requests over asynchronous
440 one, this value should be decreased relative to fifo_expire_async.
441
442 low_latency
443 -----------
444
445 This parameter is used to enable/disable BFQ's low latency mode. By
446 default, low latency mode is enabled. If enabled, interactive and soft
447 real-time applications are privileged and experience a lower latency,
448 as explained in more detail in the description of how BFQ works.
449
450 DISABLE this mode if you need full control on bandwidth
451 distribution. In fact, if it is enabled, then BFQ automatically
452 increases the bandwidth share of privileged applications, as the main
453 means to guarantee a lower latency to them.
454
455 In addition, as already highlighted at the beginning of this document,
456 DISABLE this mode if your only goal is to achieve a high throughput.
457 In fact, privileging the I/O of some application over the rest may
458 entail a lower throughput. To achieve the highest-possible throughput
459 on a non-rotational device, setting slice_idle to 0 may be needed too
460 (at the cost of giving up any strong guarantee on fairness and low
461 latency).
462
463 timeout_sync
464 ------------
465
466 Maximum amount of device time that can be given to a task (queue) once
467 it has been selected for service. On devices with costly seeks,
468 increasing this time usually increases maximum throughput. On the
469 opposite end, increasing this time coarsens the granularity of the
470 short-term bandwidth and latency guarantees, especially if the
471 following parameter is set to zero.
472
473 max_budget
474 ----------
475
476 Maximum amount of service, measured in sectors, that can be provided
477 to a BFQ queue once it is set in service (of course within the limits
478 of the above timeout). According to what was said in the description of
479 the algorithm, larger values increase the throughput in proportion to
480 the percentage of sequential I/O requests issued. The price of larger
481 values is that they coarsen the granularity of short-term bandwidth
482 and latency guarantees.
483
484 The default value is 0, which enables auto-tuning: BFQ sets max_budget
485 to the maximum number of sectors that can be served during
486 timeout_sync, according to the estimated peak rate.
487
488 For specific devices, some users have occasionally reported to have
489 reached a higher throughput by setting max_budget explicitly, i.e., by
490 setting max_budget to a higher value than 0. In particular, they have
491 set max_budget to higher values than those to which BFQ would have set
492 it with auto-tuning. An alternative way to achieve this goal is to
493 just increase the value of timeout_sync, leaving max_budget equal to 0.
494
495 4. Group scheduling with BFQ
496 ============================
497
498 BFQ supports both cgroups-v1 and cgroups-v2 io controllers, namely
499 blkio and io. In particular, BFQ supports weight-based proportional
500 share. To activate cgroups support, set BFQ_GROUP_IOSCHED.
501
502 4-1 Service guarantees provided
503 -------------------------------
504
505 With BFQ, proportional share means true proportional share of the
506 device bandwidth, according to group weights. For example, a group
507 with weight 200 gets twice the bandwidth, and not just twice the time,
508 of a group with weight 100.
509
510 BFQ supports hierarchies (group trees) of any depth. Bandwidth is
511 distributed among groups and processes in the expected way: for each
512 group, the children of the group share the whole bandwidth of the
513 group in proportion to their weights. In particular, this implies
514 that, for each leaf group, every process of the group receives the
515 same share of the whole group bandwidth, unless the ioprio of the
516 process is modified.
517
518 The resource-sharing guarantee for a group may partially or totally
519 switch from bandwidth to time, if providing bandwidth guarantees to
520 the group lowers the throughput too much. This switch occurs on a
521 per-process basis: if a process of a leaf group causes throughput loss
522 if served in such a way to receive its share of the bandwidth, then
523 BFQ switches back to just time-based proportional share for that
524 process.
525
526 4-2 Interface
527 -------------
528
529 To get proportional sharing of bandwidth with BFQ for a given device,
530 BFQ must of course be the active scheduler for that device.
531
532 Within each group directory, the names of the files associated with
533 BFQ-specific cgroup parameters and stats begin with the "bfq."
534 prefix. So, with cgroups-v1 or cgroups-v2, the full prefix for
535 BFQ-specific files is "blkio.bfq." or "io.bfq." For example, the group
536 parameter to set the weight of a group with BFQ is blkio.bfq.weight
537 or io.bfq.weight.
538
539 As for cgroups-v1 (blkio controller), the exact set of stat files
540 created, and kept up-to-date by bfq, depends on whether
541 CONFIG_BFQ_CGROUP_DEBUG is set. If it is set, then bfq creates all
542 the stat files documented in
543 Documentation/admin-guide/cgroup-v1/blkio-controller.rst. If, instead,
544 CONFIG_BFQ_CGROUP_DEBUG is not set, then bfq creates only the files::
545
546 blkio.bfq.io_service_bytes
547 blkio.bfq.io_service_bytes_recursive
548 blkio.bfq.io_serviced
549 blkio.bfq.io_serviced_recursive
550
551 The value of CONFIG_BFQ_CGROUP_DEBUG greatly influences the maximum
552 throughput sustainable with bfq, because updating the blkio.bfq.*
553 stats is rather costly, especially for some of the stats enabled by
554 CONFIG_BFQ_CGROUP_DEBUG.
555
556 Parameters
557 ----------
558
559 For each group, the following parameters can be set:
560
561 weight
562 This specifies the default weight for the cgroup inside its parent.
563 Available values: 1..1000 (default: 100).
564
565 For cgroup v1, it is set by writing the value to `blkio.bfq.weight`.
566
567 For cgroup v2, it is set by writing the value to `io.bfq.weight`.
568 (with an optional prefix of `default` and a space).
569
570 The linear mapping between ioprio and weights, described at the beginning
571 of the tunable section, is still valid, but all weights higher than
572 IOPRIO_BE_NR*10 are mapped to ioprio 0.
573
574 Recall that, if low-latency is set, then BFQ automatically raises the
575 weight of the queues associated with interactive and soft real-time
576 applications. Unset this tunable if you need/want to control weights.
577
578 weight_device
579 This specifies a per-device weight for the cgroup. The syntax is
580 `minor:major weight`. A weight of `0` may be used to reset to the default
581 weight.
582
583 For cgroup v1, it is set by writing the value to `blkio.bfq.weight_device`.
584
585 For cgroup v2, the file name is `io.bfq.weight`.
586
587
588 [1]
589 P. Valente, A. Avanzini, "Evolution of the BFQ Storage I/O
590 Scheduler", Proceedings of the First Workshop on Mobile System
591 Technologies (MST-2015), May 2015.
592
593 http://algogroup.unimore.it/people/paolo/disk_sched/mst-2015.pdf
594
595 [2]
596 P. Valente and M. Andreolini, "Improving Application
597 Responsiveness with the BFQ Disk I/O Scheduler", Proceedings of
598 the 5th Annual International Systems and Storage Conference
599 (SYSTOR '12), June 2012.
600
601 Slightly extended version:
602
603 http://algogroup.unimore.it/people/paolo/disk_sched/bfq-v1-suite-results.pdf
604
605 [3]
606 https://github.com/Algodev-github/S
607

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

BFQ의 목적과 처리 비용

1-59

`BFQ (Budget Fair Queueing)`는 proportional-share I/O scheduler이며 추가적인 low-latency 기능을 제공합니다. `blkio` 또는 `io` controller를 통한 cgroup 지원과 함께 다음 두 기능이 핵심입니다.

  • system과 application의 높은 responsiveness를 보장하고 audio·video player 같은 time-sensitive application의 latency를 낮춥니다.
  • process 또는 group 사이에 device time만이 아니라 bandwidth를 분배합니다. throughput을 높여야 할 때는 time distribution으로 되돌아갑니다.

기본 설정에서 BFQ는 throughput보다 latency를 우선합니다. 낮은 latency를 위해 throughput이 줄어드는 schedule을 만들 수 있습니다. 특정 device에서 항상 가능한 최대 throughput만 원한다면 `low_latency`를 `0`으로 설정해 모든 low-latency heuristic을 끄십시오. latency·throughput tradeoff와 최대 throughput 설정은 Section 3에서 설명합니다.

다른 I/O scheduler처럼 BFQ도 request 처리 overhead를 더합니다. request insertion·dispatch·completion hook의 실행 시간을 합친 single-lock-protected per-request 시간은 Intel Core [email protected]에서 약 `1.9 us`였습니다. simple code instrumentation과 S suite [1]의 `throughput-sync.sh`를 performance-profiling mode로 사용한 수치입니다.

비교하면 `blk-mq`에서 가장 가벼운 I/O scheduler인 `mq-deadline`의 같은 실행 시간은 `0.7 us`입니다. code 규모는 mq-deadline 약 `800 LOC`, BFQ 약 `10500 LOC`입니다.

scheduling overhead는 I/O stack 나머지 부분의 비용과 함께 CPU가 처리할 수 있는 최대 IOPS도 제한합니다. full hierarchy support인 `CONFIG_BFQ_GROUP_IOSCHED`를 켠 세 system의 지속 가능한 BFQ 처리량은 다음과 같습니다.

CPU / system class`CONFIG_BFQ_CGROUP_DEBUG` unset`CONFIG_BFQ_CGROUP_DEBUG` set
Intel i7-4850HQ, average laptop`400 KIOPS``310 KIOPS`
AMD A8-3850, old desktop`250 KIOPS``200 KIOPS`
ARM CortexTM-A53 Octa-core, cheap embedded`80 KIOPS``56 KIOPS`

`CONFIG_BFQ_CGROUP_DEBUG`를 켜면 모든 `blkio.bfq*` statistic을 생성·갱신하므로 지속 가능한 throughput이 감소합니다. BFQ는 multi-queue device에서도 동작합니다.

문서 구성

60-72

원문의 목차는 다음 네 영역과 하위 절로 구성됩니다.

  • 1. BFQ가 유용한 경우: personal system과 server system
  • 2. BFQ 동작 방식
  • 3. BFQ tunable과 올바른 설정
  • 4. BFQ group scheduling: service guarantee와 interface

personal system에서의 이점

73-136

BFQ는 personal system과 server system 모두에 이점을 제공하며, personal system에서는 interactive application latency를 특히 낮춥니다. 실제 background workload와 관계없이 storage device가 idle인 것과 거의 같은 responsiveness를 interactive task에 보장합니다.

다음 background workload가 하나 이상 실행 중이어도 이 특성을 유지합니다.

  • 큰 file 하나 이상을 read, write 또는 copy
  • source-file tree compile
  • virtual machine 하나 이상의 I/O
  • software update
  • indexing daemon의 filesystem scan과 database update

따라서 application 시작이나 application 안에서 file load에 걸리는 시간은 device가 idle일 때와 비슷합니다. 같은 조건의 `CFQ`, `NOOP`, `DEADLINE`에서는 SSD에서도 background workload가 끝날 때까지 latency가 높아지거나 application이 응답하지 않을 수 있습니다.

audio·video player 또는 streamer 같은 soft real-time application도 background I/O workload와 관계없이 낮은 latency와 drop rate를 얻으므로 background workload로 인한 glitch가 거의 없습니다.

추가 workload가 병렬 실행될 때 compile, checkout, merge 같은 일반 code-development task의 I/O component도 `CFQ`, `NOOP`, `DEADLINE`보다 훨씬 빠르게 실행합니다.

hard disk의 sequential workload에서는 CFQ보다 최대 30%, DEADLINE과 NOOP보다 최대 150% 높은 throughput을 달성했습니다. random workload와 flash-based device의 모든 workload에서는 다른 scheduler와 대체로 같은 throughput을 냅니다.

BFQ는 workload와 device parameter에 관계없이 I/O-bound application의 weight에 비례해 device time이 아니라 device throughput을 분배합니다. 이 bandwidth guarantee에서 간단한 formula로 tight per-I/O-request delay guarantee를 계산할 수 있습니다. strict service guarantee로 설정하지 않았다면 bandwidth share 때문에 throughput이 감소하는 application에만 time-based resource sharing으로 전환합니다.

server system에서의 이점

137-154

server system의 이점도 같은 service property에서 나옵니다. 추가로 무거운 workload를 처리하는지와 관계없이 BFQ는 다음을 보장합니다.

  • audio·video streaming의 jitter와 drop rate가 0 또는 매우 낮음
  • WEB page와 embedded object의 빠른 retrieval
  • packet logging 같은 live-dumping application의 real-time data recording
  • server에 대한 local·remote access responsiveness

budget scheduling과 B-WF2Q+

155-295

BFQ는 general structure와 많은 code를 CFQ에서 가져온 proportional-share I/O scheduler입니다. device에서 I/O를 수행하는 각 process는 weight와 `(bfq_)queue`에 연결됩니다.

BFQ는 한 번에 한 queue, 즉 한 process에 일정 시간 device 독점 access를 부여합니다. 각 queue에는 sector 수로 측정한 budget이 있고, service를 받은 뒤 request를 dispatch할 때마다 request size만큼 budget을 줄입니다.

in-service queue는 다음 사건 중 하나가 발생할 때만 expire되어 service가 중단됩니다.

  • queue가 budget을 모두 사용함
  • queue가 비어 있음
  • `budget timeout` 발생

`budget timeout`은 random I/O process가 device를 너무 오래 점유해 throughput을 크게 낮추는 일을 막습니다. CFQ처럼 sync request를 내는 process의 queue는 비었을 때 즉시 expire되지 않을 수 있습니다. BFQ는 잠시 device를 idle 상태로 두어 process가 제때 새 request를 내면 계속 service받게 합니다.

device idling은 synchronous sequential I/O에서 rotational device와 command queueing이 없는 flash device의 throughput을 높이는 경우가 많습니다. BFQ에서는 sync request process에 원하는 throughput fraction을 보장하는 수단이기도 하며 자세한 내용은 `slice_idle` 설명과 [1, 2]에 있습니다.

동시에 경쟁하는 process가 여럿이어도 모든 process와 group의 weight가 같다면 BFQ는 device를 idle시키지 않고 예상 throughput 분배를 보장합니다. 이 흔한 상황에서는 throughput을 최대한 유지합니다.

internal command queueing, 보통 `NCQ`를 사용하는 flash storage에서는 device idling이 항상 throughput에 해롭습니다. BFQ는 low latency나 fairness 같은 service guarantee에 반드시 필요할 때만 idling합니다. 이때 전체 throughput은 최적보다 낮을 수 있으며, internal queueing device에서 강한 service guarantee와 최적 throughput을 동시에 제공하는 해법은 현재 없습니다.

기본값인 low-latency mode에서는 interactive application과 soft real-time application을 감지해 latency를 줄이는 heuristic을 실행합니다. 핵심은 관련 queue에 fair share보다 많은 device throughput을 주는 `weight-raising`입니다. interactive application에는 완만하게, soft real-time application에는 더 강하게 적용합니다.

BFQ는 queue가 한꺼번에 생성되는 burst에서 태어난 queue에는 idling을 자동으로 끕니다. 이런 queue는 대개 boot 중 `systemd`나 `git grep`처럼 high throughput의 이점이 큰 application·service process에 연결되기 때문입니다.

CFQ처럼 BFQ도 섞어서 보면 대부분 sequential이 되는 interleaved random I/O queue를 merge합니다. BFQ의 `Early Queue Merge (EQM)`은 cooperating process를 더 빠르게 감지해, CFQ가 preemption을 써야 높은 throughput을 얻는 queue에도 merge 하나로 높은 throughput을 제공합니다.

queue scheduling에는 augmented rb-tree로 구현한 `WF2Q+` variant인 `B-WF2Q+`를 사용해 전체 complexity를 `O(log N)`으로 유지합니다. 자세한 내용은 [2]에 있으며 hierarchical scheduling도 지원합니다.

`B-WF2Q+`는 이상적으로 완전히 fair하고 smooth한 service와의 deviation을 작게 제한합니다. device throughput이 변해도 각 queue가 weight에 비례한 throughput fraction을 받으며 device parameter, 현재 workload, queue budget에 의존하지 않습니다.

budget independence에는 두 이점이 있습니다. 첫째, proportional-share scheduler의 이상적 service 대비 최대 deviation은 최대 budget에 비례하지만 BFQ는 높은 throughput share를 주려고 queue budget을 키울 필요가 없습니다. 정확한 `B-WF2Q+` service와 함께 deviation을 작게 유지할 수 있습니다.

둘째, BFQ는 process 요구와 I/O pattern에 가장 맞는 budget을 자유롭게 고를 수 있습니다. simple feedback-loop algorithm은 throughput을 높이면서 time-sensitive application의 tight latency guarantee를 유지하도록 queue expiration 때 다음 budget을 계산합니다.

  • sequential I/O를 수행하는 I/O-bound application queue에는 결국 큰 budget을 줍니다. device access를 얻은 뒤 오래 service할수록 throughput이 높기 때문입니다.
  • sporadic하고 짧은 I/O를 내는 time-sensitive application queue에는 결국 작은 budget을 줍니다. service를 기다리는 queue의 budget이 작을수록 `B-WF2Q+`가 더 빨리 service합니다([2] Subsec 3.3).

모든 process와 group의 weight가 같을 때는 idling 대신 preemption으로 예상 throughput을 분배해 이 흔한 상황의 throughput을 크게 높입니다. `ioprio` class는 strict priority 순서로 service하므로 높은 priority queue가 남아 있는 동안 낮은 priority queue는 service하지 않습니다. 같은 class 안에서는 weight에 비례해 bandwidth를 나누되 starvation 방지를 위해 Idle class에도 아주 적은 추가 bandwidth를 보장합니다.

tunable 개요와 process weight

296-326

대부분 BFQ tunable은 latency·fairness 같은 service guarantee와 throughput에 영향을 줍니다. tradeoff는 `slice_idle`, `strict_guarantees`, `low_latency`를, throughput 최대화는 `slice_idle`, `timeout_sync`, `max_budget`을 보십시오.

나머지 performance parameter는 CFQ에서 상속되어 주로 compatibility를 위해 남았습니다. 지금까지 BFQ에서 이 값을 바꿔 performance가 개선되었다는 보고는 없습니다. `back_seek_max`, `back_seek_penalty`, `fifo_expire_async`, `fifo_expire_sync` 설명은 CFQ의 설명을 그대로 가져왔고 `slice_idle` 설명 일부도 같습니다.

cgroup interface를 쓰지 않으면 process weight는 I/O priority를 통해서만 간접 지정하며 관계식은 다음과 같습니다.

weight = (IOPRIO_BE_NR - ioprio) * 10.

`low_latency`가 설정되면 BFQ가 interactive·soft real-time application queue의 weight를 자동으로 올립니다. weight를 직접 제어해야 한다면 이 tunable을 해제하십시오.

slice_idle의 throughput·보장 tradeoff

327-380

`slice_idle`은 일부 sync BFQ queue가 비었을 때 다음 I/O request를 기다리며 BFQ가 idle할 시간을 지정합니다. 기본값은 0이 아니며, idling은 throughput 향상과 원하는 throughput 분배 준수라는 두 목적을 가집니다.

single-spindle SATA/SAS disk처럼 seek가 많은 media에서는 전체 seek 수를 줄여 throughput을 높일 수 있습니다. 반대로 `slice_idle=0`은 모든 queue idling을 없애므로 hardware RAID의 여러 SATA/SAS disk나 internal command queueing과 parallelism을 가진 flash storage에서 전체 throughput이 좋아질 수 있습니다.

일반적으로 SATA/SAS disk와 그 software RAID에서는 idling을 유지하는 편이 유용합니다. 하나의 LUN 뒤에 spindle이 여러 개 있는 host hardware RAID·storage array나 빠른 flash storage에서는 `slice_idle=0`이 더 좋은 throughput과 받아들일 만한 latency를 낼 수 있습니다.

하지만 weight나 I/O-request length가 서로 다를 때 service guarantee를 강제하려면 idling이 필요합니다. queue A가 queue B의 request 하나마다 여러 request를 service받아야 한다고 가정하면, A가 빈 직후 새 request를 내는 사이에 B request가 끼어 dispatch되지 않도록 idling해야 A가 차등 share를 잃지 않습니다.

idling만으로 보장하는 차등 처리는 I/O-request dispatch 순서에 한정됩니다. 실제 service 순서도 dispatch 순서를 따르게 하려면 `strict_guarantees`도 설정해야 합니다.

throughput에도 유리한 경우를 제외하면 idling은 특히 random workload에서 throughput을 크게 낮출 수 있습니다. BFQ는 throughput에 유리하지 않은 idling을 가능한 한 피합니다. 그 결과와 `strict_guarantees`에서 설명할 문제 때문에 단기 service guarantee가 가끔 깨질 수 있습니다.

video playback·streaming처럼 최대 throughput보다 매우 낮은 drop rate가 더 중요하다면 `strict_guarantees` 설정을 고려하십시오.

slice_idle_us와 strict_guarantees

381-407

`slice_idle_us`는 `slice_idle`과 같은 parameter를 microsecond 단위로 제어합니다. 어느 쪽으로든 idling behavior를 설정할 수 있고, 이후 다른 tunable의 sysfs 값도 새 값으로 갱신됩니다.

기본값이 unset인 `strict_guarantees`를 설정하면 BFQ는 다음을 수행합니다.

  • in-service queue가 비면 항상 idling합니다.
  • outstanding request가 없을 때만 새 request를 dispatch해 device가 한 번에 I/O request 하나만 service하도록 강제합니다.

weight 또는 I/O-request size가 서로 다를 때 각 BFQ queue가 할당된 bandwidth share를 받으려면 두 조건이 모두 필요합니다. 첫 조건의 이유는 `slice_idle` 설명과 같고, 둘째 조건은 modern storage device가 내부 queue의 request를 reorder해 I/O scheduler의 service guarantee를 쉽게 깨뜨릴 수 있기 때문입니다.

`strict_guarantees`를 설정하면 throughput에 영향을 줄 수 있습니다.

back seek와 FIFO timeout

408-441
Tunable단위·기본값동작
`back_seek_max`Kbytes현재 head location보다 뒤쪽 sector를 다음 request로 간주할 수 있는 최대 backward seek distance
`back_seek_penalty`default `2`backward request distance가 front request의 `1/back_seek_penalty`이면 두 seek cost를 같게 봅니다. 그렇지 않으면 front request 쪽으로 bias합니다.
`fifo_expire_async`default `250ms`asynchronous request timeout
`fifo_expire_sync`default `125ms`synchronous request timeout. sync request를 async보다 우선하려면 `fifo_expire_async`에 비해 이 값을 낮춥니다.

low_latency·timeout_sync·max_budget

442-494

`low_latency`는 BFQ low-latency mode를 켜거나 끕니다. 기본값은 enabled이며 interactive·soft real-time application을 우대해 앞의 algorithm 설명처럼 latency를 낮춥니다.

bandwidth 분배를 완전히 제어하려면 이 mode를 끄십시오. 켜져 있으면 낮은 latency를 보장하는 핵심 수단으로 BFQ가 privileged application의 bandwidth share를 자동으로 늘립니다.

목표가 high throughput뿐인 경우에도 끄십시오. 일부 application I/O를 우대하면 throughput이 줄 수 있습니다. non-rotational device에서 가능한 최고 throughput을 내려면 `slice_idle=0`도 필요할 수 있으며, 그 대가로 fairness와 low latency에 대한 강한 보장을 포기합니다.

`timeout_sync`는 service 대상으로 선택된 task(queue)에 줄 수 있는 최대 device time입니다. seek cost가 큰 device에서는 이 시간을 늘리면 보통 최대 throughput이 높아지지만, 단기 bandwidth·latency guarantee의 granularity는 거칠어지며 특히 `max_budget`이 0일 때 그렇습니다.

`max_budget`은 in-service BFQ queue에 제공할 수 있는 sector 단위 최대 service 양이며 `timeout_sync` 한도 안에서 적용됩니다. 값이 클수록 sequential I/O request 비율에 따라 throughput이 늘지만 단기 bandwidth·latency guarantee의 granularity가 거칠어집니다.

기본값 `0`은 auto-tuning을 활성화합니다. BFQ가 estimated peak rate에 따라 `timeout_sync` 동안 service할 수 있는 최대 sector 수로 `max_budget`을 정합니다.

일부 device에서는 사용자가 `max_budget`을 0보다 큰 값, 특히 auto-tuning보다 큰 값으로 명시해 더 높은 throughput을 얻었다고 보고했습니다. 같은 목표는 `max_budget=0`을 유지하고 `timeout_sync`를 늘리는 방법으로도 달성할 수 있습니다.

BFQ group scheduling 보장

495-525

BFQ는 cgroups-v1 `blkio`와 cgroups-v2 `io` controller를 모두 지원하며 weight 기반 proportional share를 제공합니다. cgroup 지원을 활성화하려면 `BFQ_GROUP_IOSCHED`를 설정합니다.

BFQ에서 proportional share는 group weight에 따른 실제 device bandwidth share입니다. 예를 들어 weight 200 group은 weight 100 group보다 device time뿐 아니라 bandwidth를 두 배 받습니다.

BFQ는 깊이에 제한 없는 hierarchy(group tree)를 지원합니다. 각 group의 child는 weight에 비례해 parent group 전체 bandwidth를 나눕니다. 각 leaf group의 process는 process `ioprio`를 바꾸지 않는 한 group 전체 bandwidth에서 같은 share를 받습니다.

group에 bandwidth guarantee를 제공하느라 throughput이 지나치게 낮아지면 resource-sharing guarantee가 일부 또는 전부 bandwidth에서 time으로 바뀔 수 있습니다. 이 전환은 process 단위입니다. leaf group process를 bandwidth share대로 service할 때 throughput loss를 일으키면 BFQ는 그 process만 time-based proportional share로 되돌립니다.

cgroup interface와 debug statistic

526-555

특정 device에 BFQ bandwidth proportional sharing을 적용하려면 BFQ가 그 device의 active scheduler여야 합니다.

각 group directory의 BFQ 전용 cgroup parameter와 statistic file 이름은 `bfq.`로 시작합니다. 전체 prefix는 cgroups-v1에서 `blkio.bfq.`, cgroups-v2에서 `io.bfq.`입니다. 예를 들어 group weight parameter는 `blkio.bfq.weight` 또는 `io.bfq.weight`입니다.

cgroups-v1 `blkio` controller에서 생성·갱신하는 정확한 stat file 집합은 `CONFIG_BFQ_CGROUP_DEBUG`에 따라 달라집니다. 설정하면 `Documentation/admin-guide/cgroup-v1/blkio-controller.rst`에 문서화된 모든 stat file을 만들고, 설정하지 않으면 다음 네 file만 만듭니다.

blkio.bfq.io_service_bytes
blkio.bfq.io_service_bytes_recursive
blkio.bfq.io_serviced
blkio.bfq.io_serviced_recursive

`blkio.bfq.*` statistic 갱신 비용, 특히 `CONFIG_BFQ_CGROUP_DEBUG`가 켜는 일부 statistic의 비용이 크므로 이 config 값은 BFQ가 지속할 수 있는 최대 throughput에 큰 영향을 줍니다.

group parameter와 참고문헌

556-606

각 group에는 다음 parameter를 설정할 수 있습니다.

Parameter범위·syntaxcgroup v1 / v2와 동작
`weight``1..1000`, `default: 100`parent 안에서 cgroup의 default weight입니다. v1은 `blkio.bfq.weight`, v2는 `io.bfq.weight`에 쓰며 v2 값 앞에 선택적으로 `default `를 붙일 수 있습니다.
`weight_device``minor:major weight`; `0`은 default로 resetdevice별 cgroup weight입니다. v1은 `blkio.bfq.weight_device`, v2 file은 `io.bfq.weight`입니다.

tunable 절 앞부분의 ioprio와 weight 사이 linear mapping은 그대로 유효하지만 `IOPRIO_BE_NR*10`보다 큰 모든 weight는 ioprio 0으로 mapping됩니다. `low_latency`가 켜져 있으면 interactive·soft real-time queue의 weight를 BFQ가 자동으로 올리므로 직접 제어하려면 이 tunable을 끕니다.

[1] P. Valente, A. Avanzini, "Evolution of the BFQ Storage I/O Scheduler", First Workshop on Mobile System Technologies (MST-2015), May 2015: http://algogroup.unimore.it/people/paolo/disk_sched/mst-2015.pdf

[2] P. Valente, M. Andreolini, "Improving Application Responsiveness with the BFQ Disk I/O Scheduler", 5th Annual International Systems and Storage Conference (SYSTOR '12), June 2012. Slightly extended version: http://algogroup.unimore.it/people/paolo/disk_sched/bfq-v1-suite-results.pdf

[3] https://github.com/Algodev-github/S