书接上文提到的两个方案。
调整 group_idle 参数
之前的思路是:调整 group_idle 参数,在 idle 时让 queue 和 group 空转,多等待下一个 request 一会儿。
so,编写脚本,测试不同 group_idle 值下,不同 cgroup 组的 IO 速率,以及系统总 IO 速率。
top-app : foreground : normal : background = 1000 : 500 : 300 : 100
group_idle/us | total IO speed/(MB/s) | top-app | foreground | normal | background |
---|---|---|---|---|---|
0 | 659 | 164 | 166 | 163 | 166 |
1000 | 669 | 329 | 107 | 147 | 86 |
2000 | 362 | 166 | 87 | 57 | 52 |
3000 | 328 | 149 | 78 | 53 | 48 |
4000 | 352 | 156 | 86 | 58 | 52 |
5000 | 351 | 161 | 82 | 57 | 51 |
6000 | 269 | 111 | 66 | 48 | 44 |
7000 | 317 | 146 | 73 | 51 | 47 |
8000 | 400 | 195 | 89 | 61 | 55 |
9000 | 329 | 146 | 79 | 55 | 49 |
10000 | 279 | 113 | 70 | 50 | 46 |
可以看到 group_idle 为 1 ms 时,总 IO 速率基本保持不变,而各组基本和 weight 挂钩。
这里有两个异常现象:
Q1. 加了 group_idle 延迟后,总 IO 速率反而提高了 10 M/s ?
Q2. normal 速率居然比 foreground 要高?
于是再次看 log:
A1. 比起之前少了很多 queue 和 group 的插入删除操作,所以更快了
A2. normal 为 parent cgroup,在 cfq_should_preempt 里判断为可以抢占子 group。
这里的 A2 莫名其妙,明明 parent 的 leaf_weight 比 child 的 weight 低,为什么可以抢占?当时设计时没有参考 weight 吗?
根据 3984aa5: cfq-iosched: Allow parent cgroup to preempt its child ,通常 ext4 的 journal 线程都存在 parent group 里,而工作负载线程为了控制速率,都在 child group 里。为了减少工作负载被 journal 阻塞,这里设计为允许 parent 抢占 child group。
这其实启示我们把工作负载放到一个子 group 里,哪怕把子 group 的 weight 和 parent 设为一致。
所以这个方案 OK 吗?仔细想想还有些不妥,dd 这样的连续顺序读取在 android 的 IO 场景里占比并不多。这样虽然能提高顺序读的性能,但对突发 IO 也附加 1ms 的就没有必要了。
除非能根据 IO 模式动态调整 group_idle,现阶段还是保持取消 group_idle 为好。
使用异步同时下发多个请求
之前想使用异步同时下发多个请求,使 IO 插入速率大于 IO 处理速率。这样就能一直保持 cfq queue 里有 request,从而 group 不会从 service tree 里删除,后面就能根据之前的 vdisktime 调度 group。
之前一直是用 dd 测的,因为我的 fio 里没有 libaio 库,只能自己编译一下。但是执行出错 shmget: Function not implemented error: failed to setup shm segment
。查阅资料后,带 CONFIG_SYSVIPC=y
重新编译 kernel。
另外,cfq 默认一个请求时间(算上寻道)不可能小于 1 jiffies。在调试过程中,把这个限制取消了。
OK,现在 cgroup 的威力终于展现出来了。
4 group 竞争下发 IO 速率
(无加压,随机读写 16-thread 4k 负载)
group | Speed MB/s |
---|---|
Background | 0.3 |
Default | 0.9 |
Foreground | 17 |
Top-App | 28 |
加压后各 group IO 速率
(32-thread 4k 加压,随机读写 32-thread 4k 负载)
group | Speed MB/s |
---|---|
Background | 17 |
Default | 25 |
Foreground | 31 |
Top-App | 36 |
加压 Androbench 测试
(32-thread 4K 加压,随机读写 32-thread 4K 负载)
group | SeqR MB/s | SeqW MB/s | RandR MB/s | RandW MB/s |
---|---|---|---|---|
No-pressure | 1002 | 455 | 312 | 137 |
Default group | 895 | 227 | 46 | 30 |
Top-app group | 931 | 256 | 95 | 47 |
目前一切基本符合预期结果