Advertisement
Guest User

[RFC PATCH] cfq-iosched: limit slice_idle when many busy que

a guest
Sep 2nd, 2013
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.83 KB | None | 0 0
  1. Hi,
  2.  
  3. When some application launches several hundreds of processes that issue
  4. only a few small sync I/O requests, CFQ may cause heavy latencies
  5. (10+ seconds at the worst case), although the request rate is low enough for
  6. the disk to handle it without waiting. This is because CFQ waits for
  7. slice_idle (default:8ms) every time before processing each request, until
  8. their thinktimes are evaluated.
  9.  
  10. This scenario can be reproduced using fio with parameters below:
  11. fio -filename=/tmp/test -rw=randread -size=5G -runtime=15 -name=file1 \
  12. -bs=4k -numjobs=500 -thinktime=1000000
  13. In this case, 500 processes issue a random read request every second.
  14.  
  15. This problem can be avoided by setting slice_idle to 0, but there is a
  16. risk to hurt throughput performance on S-ATA disks.
  17.  
  18. This patch tries to reduce the effect of slice_idle automatically when a
  19. lot of busy queues are waiting in the idle window.
  20. It adds a counter (busy_idle_queues) of queues in idle window that have
  21. I/O requests to cfq_data. And if (busy_idle_queues * slice_idle) goes over
  22. the slice allocated to the group, it limits the idle wait time to
  23. (group_slice / busy_idle_queues).
  24.  
  25. Without this patch, fio benchmark with parameters above to an ext4
  26. partition on a S-ATA HDD results in:
  27. read : io=20140KB, bw=1258.5KB/s, iops=314 , runt= 16004msec
  28. clat (usec): min=4 , max=6494.9K, avg=541264.54, stdev=993834.12
  29.  
  30. With this patch:
  31. read : io=28040KB, bw=1750.1KB/s, iops=437 , runt= 16014msec
  32. clat (usec): min=4 , max=2837.2K, avg=110236.79, stdev=303351.72
  33.  
  34. Average latency is reduced by 80%, and max is also reduced by 56%.
  35.  
  36. Any comments are appreciated.
  37.  
  38. Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
  39. ---
  40. block/cfq-iosched.c | 36 +++++++++++++++++++++++++++++++-----
  41. 1 file changed, 31 insertions(+), 5 deletions(-)
  42.  
  43. diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
  44. index d5cd313..77ac27e80 100644
  45. --- a/block/cfq-iosched.c
  46. +++ b/block/cfq-iosched.c
  47. @@ -329,6 +329,7 @@ struct cfq_data {
  48.  
  49. unsigned int busy_queues;
  50. unsigned int busy_sync_queues;
  51. + unsigned int busy_idle_queues; /* busy but with idle window */
  52.  
  53. int rq_in_driver;
  54. int rq_in_flight[2];
  55. @@ -446,6 +447,20 @@ CFQ_CFQQ_FNS(deep);
  56. CFQ_CFQQ_FNS(wait_busy);
  57. #undef CFQ_CFQQ_FNS
  58.  
  59. +static inline void cfq_set_cfqq_idle_window(struct cfq_data *cfqd,
  60. + struct cfq_queue *cfqq, bool idle)
  61. +{
  62. + if (idle) {
  63. + cfq_mark_cfqq_idle_window(cfqq);
  64. + if (cfq_cfqq_on_rr(cfqq))
  65. + cfqd->busy_idle_queues++;
  66. + } else {
  67. + cfq_clear_cfqq_idle_window(cfqq);
  68. + if (cfq_cfqq_on_rr(cfqq))
  69. + cfqd->busy_idle_queues--;
  70. + }
  71. +}
  72. +
  73. static inline struct cfq_group *pd_to_cfqg(struct blkg_policy_data *pd)
  74. {
  75. return pd ? container_of(pd, struct cfq_group, pd) : NULL;
  76. @@ -2164,6 +2179,8 @@ static void cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  77. cfqd->busy_queues++;
  78. if (cfq_cfqq_sync(cfqq))
  79. cfqd->busy_sync_queues++;
  80. + if (cfq_cfqq_idle_window(cfqq))
  81. + cfqd->busy_idle_queues++;
  82.  
  83. cfq_resort_rr_list(cfqd, cfqq);
  84. }
  85. @@ -2192,6 +2209,8 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  86. cfqd->busy_queues--;
  87. if (cfq_cfqq_sync(cfqq))
  88. cfqd->busy_sync_queues--;
  89. + if (cfq_cfqq_idle_window(cfqq))
  90. + cfqd->busy_idle_queues--;
  91. }
  92.  
  93. /*
  94. @@ -2761,6 +2780,16 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
  95. else
  96. sl = cfqd->cfq_slice_idle;
  97.  
  98. + /*
  99. + * If there too many queues with idle window, slice idle can cause
  100. + * unacceptable latency. Then we reduce slice idle here.
  101. + */
  102. + if (cfqd->busy_idle_queues) {
  103. + unsigned group_slice = cfq_group_slice(cfqd, cfqq->cfqg);
  104. + unsigned long limit = group_slice / cfqd->busy_idle_queues;
  105. + sl = min(sl, limit);
  106. + }
  107. +
  108. mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
  109. cfqg_stats_set_start_idle_time(cfqq->cfqg);
  110. cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu group_idle: %d", sl,
  111. @@ -3091,7 +3120,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
  112. (cfq_cfqq_slice_new(cfqq) ||
  113. (cfqq->slice_end - jiffies > jiffies - cfqq->slice_start))) {
  114. cfq_clear_cfqq_deep(cfqq);
  115. - cfq_clear_cfqq_idle_window(cfqq);
  116. + cfq_set_cfqq_idle_window(cfqd, cfqq, false);
  117. }
  118.  
  119. if (cfqq->dispatched && cfq_should_idle(cfqd, cfqq)) {
  120. @@ -3742,10 +3771,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  121.  
  122. if (old_idle != enable_idle) {
  123. cfq_log_cfqq(cfqd, cfqq, "idle=%d", enable_idle);
  124. - if (enable_idle)
  125. - cfq_mark_cfqq_idle_window(cfqq);
  126. - else
  127. - cfq_clear_cfqq_idle_window(cfqq);
  128. + cfq_set_cfqq_idle_window(cfqd, cfqq, enable_idle);
  129. }
  130. }
  131.  
  132.  
  133. --
  134. To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
  135. the body of a message to majordomo@vger.kernel.org
  136. More majordomo info at http://vger.kernel.org/majordomo-info.html
  137. Please read the FAQ at http://www.tux.org/lkml/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement