为何高QPS下Socket延迟更低?基于Linux乒乓测试的疑问
定时器与线程调度的额外开销:当客户端用
usleep(1000)控制QPS时,线程休眠的1ms周期里,Linux内核定时器的精度限制(比如默认HZ配置为250时,定时器最小间隔是4ms;即便HZ=1000,实际唤醒也可能存在偏差)会导致实际休眠时间比预期更长,再加上线程唤醒后的调度延迟,这些额外时间都会计入单次请求的延迟。而usleep(10)时,休眠时间短,这部分误差和延迟的占比可以忽略,对总延迟影响极小。TCP连接空闲带来的资源调度开销:QPS=1k时,两次请求间隔长达1ms,TCP连接会进入短暂空闲状态。内核可能会降低这个连接的调度优先级,甚至回收部分socket相关的缓存资源。当新请求到来时,需要重新唤醒资源、恢复调度优先级,这一步会增加请求处理的时间。而高QPS场景下,连接一直处于活跃状态,资源始终保持就绪,完全避免了这类额外开销。
CPU缓存命中率的差异:高QPS时,客户端和服务器的socket处理逻辑被频繁执行,相关的指令、数据会一直留在CPU的L1/L2缓存里,缓存命中率极高,代码执行速度快。低QPS时,两次请求间隔太长,缓存里的内容可能被其他进程的操作冲掉,每次请求都要从内存重新加载数据和指令,自然会拉长单次请求的处理时间,拉高平均延迟。
TCP协议栈的批量优化收益:虽然已经开启
TCP_NODELAY禁用了Nagle算法,但高QPS下,请求发送频率高,内核TCP栈会持续处于活跃处理状态,中断合并、流水线处理这类微优化逻辑能充分发挥作用;而低QPS时,每个请求都是孤立触发,协议栈要从头启动单次处理流程,没有批量优化的收益,延迟自然更高。
内容的提问来源于stack exchange,提问作者ehds

