使用共享内存进行IPC时的延迟抖动问题排查
共享内存SPSC通信的延迟尖峰排查问题
实现架构
- 基于共享内存实现双进程数据传输,通过
boost::interprocess::managed_shared_memory分配vector作为环形缓冲区(大小4K,实际场景中最多仅存储1个元素) - 用原子变量实现同步逻辑,逻辑类似
boost::lockfree::spsc_queue
延迟测试设置
- 发送进程:向缓冲区写入数据后休眠,数据推送间隔约55微秒
- 接收进程:通过忙循环检查缓冲区是否可消费
- 测试次数:约300万次,以纳秒级精度记录时间戳,存储在预先扩容至300万大小的vector中
- 环境配置:6核CPU,隔离核心0-4,通过
taskset将收发进程绑定到不同核心;系统启动参数(/proc/cmdline):initrd=\initramfs-linux-lts.img root=PARTUUID=cc2a533b-d26d-4995-9166-814d7f59444d rw isolcpus=0-4 intel_idle.max_cstate=0 idle=poll - 数据验证:传输准确无丢失,直接通过时间戳逐行相减计算端到端延迟
测试结果
- 延迟均值、中位数约300-400纳秒,但标准差过高(数千纳秒)
- 存在2-3次延迟突增至600000纳秒的情况,随后延迟逐步递减(每次约56000纳秒,推测为缓冲区排队后连续消费),示例抖动数据:
568086 511243 454416 397646 340799 284018 227270 170599 113725 57022 396 - 过滤这些抖动数据后,标准差大幅降低,未发现周期性规律
已完成的排查动作
- 用
perf stat -d运行接收进程,显示上下文切换数为0;但查看/proc/${pid}/status发现,nonvoluntary_ctxt_switches以每秒约1次的速率增加,voluntary_ctxt_switches在数据传输启动后保持稳定,200秒测试仅出现2-3次尖峰,与切换频率不匹配 - 接收进程绑定核心(核心1)的上下文切换跟踪结果:
$ grep " 1)" trace | grep "=>" 1) jemallo-22010 => <idle>-0 2) <idle>-0 => kworker-138 3) kworker-138 => <idle>-0 - 测试前后
/proc/interrupts的差异对比:
| 中断名称 | 接收核心计数 | 发送核心计数 |
|---|---|---|
| enp1s0f0np1-0 | 2 | 0 |
| eno1 | 0 | 3280 |
| Non-maskable interrupts | 25 | 25 |
| Local timer interrupts | 2K | ~3M |
| Performance monitoring interrupts | 25 | 25 |
| Rescheduling interrupts | 9 | 12 |
| Function call interrupts | 120 | 110 |
| machine-check polls | 1 | 1 |
疑问与求助方向
- 不清楚为何会出现重新调度中断,以及
enp1s0f0np1-0对应的是什么设备 - 延迟尖峰的量级(600微秒)倾向于上下文切换导致,但现有排查数据不匹配,希望获得其他排查方向建议(已尝试重启服务器)
内容的提问来源于stack exchange,提问作者W1nTer003
相关产品推荐
相关产品推荐

