nr_requests 以及 queue_depth的学习与了解

发布时间 2023-06-06 06:40:33作者: 济南小老虎

nr_requests 以及 queue_depth的学习与了解


背景

冯诺依曼的计算机体系结果里面
运算器,存储器是核心. 但是将核心的产生的结果推送出去的其实是IO
IO虽然不是像运算器和存储器那么核心, 但是他的性能不好会严重的影响整体的性能响应

前段时间遇到了很多IO相关的问题, 这一块学习不是很彻底,
只是在一个周末学习了 IOWAIT和 %busy 等的概念. 
想着趁着项目间隙, 学习一下内核里面关于IO的一两个核心参数.
太多了记不住. 也没有实际意义. 

回顾

IOWAIT  理解应该是用户态IO开始到获得IO的整体时间. 他不仅包含了IO处理的时间SVCTIME 还包含了队列内的时间.
SVCTIME 是IO设备处理时间. 他主要是依靠设备的能力, 比如IOPS,吞吐量,以及寻址响应时间等. 

一个IO的处理时间核心就是这两处. SVCTIME 内核应该没法控制, 是驱动连接具体的外设来处理. 
队列的时间其实要看设备支持的队列情况, 如果硬盘支持多队列, 但是操作系统只有一个队列,那么就会浪费性能. 

%busy: busy的参数随着最近几年的计算机的迅猛发展其实已经没有了他本来的意义. 
计算模式是 队列中有IO操作的时间/抽样的实际时间. 
因为多对列的出现. 和队列深度的发展. 有任务不一定性能差, 没任务不一定性能好. 

关于nr_requests的理解

这两个参数其实不是 /proc下的内核参数
还是/sys下面的block设备的参数. 

第一个nr_requests的参数为之一般为
/sys/block/sda/queue/nr_requests
注意sda 为 设备名称 很多虚拟机一般是 vda
很多linux 默认的 队列数 512 
需要注意 这个队列的含义是队列的数量. 
之前的AHCI 接口硬盘一般只允许一个队列
队列深度为 32
最新的NVME的接口硬盘一般支持 64k个队列
每个队列支持的深度为 64k 

更多的队列会带来性能的提升. 但是队列多了对CPU资源和内存资源都有更高的要求. 
欲戴王冠必承其重. 

关于queue_depth的理解

一般queue_depth与nr_requests不在一个路径下面
nr_requests 是在 queue 目录下面 
但是 queue_depth 其实是在 device 目录下面. 
也就是说 队列的数量 其实是 队列的属性
队列的深度, 更像是设备的属性. 
设备支持的深度的情况. 
很多linux 发行版默认的数值是 1014 
cat /sys/block/sda/device/queue_depth 

如果设备有余力可以适当改大这个参数. 能够更好的实现性能. 

队列数量与队列深度的关系

队列数量是有多少IO操作在排队. 
队列深度是硬件可以支持多少IO操作同时执行. 

因为队列有写队列和读队列, 所以所有的IO队列应该是 2*nr_requests

队列深度就是真正发给设备的IO操作. 他可以体现硬件的并发能力. 
最早的HDD 支持一个队列, 队列深度是32. 就是说排队的需要少. 
一次最多可以并行执行32个IO操作. 这是磁盘电梯算法的极限了. 

现阶段SSD 已经没有磁头和步进电机的物理设备. 使用NVME的协议后他的队列数量已经得到了巨大的提升. 

其他理解

之前IO的调度有很多算法像是 deadline 后者是 cfq 算法. 
但是随着SSD设备的到来 最好的调度据说是noop

理论上计算IO需要使用不同的队列深度, 队列已经IO调度算法进行处理. 

有时候可以在生产环境上面使用 biohist 等ebpf命令获取IO 的block的大小. 
然后针对性的调整系统内核参数. 调度算法. 
然后使用FIO等工具进行压测, 获取最好的性能结果.