You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

epoll_wait存在40ms延迟导致低吞吐量问题求助

TCP本地连接下epoll_wait 40ms延迟问题排查与解决

场景与异常表现

  • 客户端与服务端部署在同一机器,通过127.0.0.1建立TCP连接
  • 客户端分两次调用send():先发送56字节消息头部,再发送512字节消息主体
  • 服务端基于epoll_wait()监听连接事件,调用recv()接收数据
  • 异常:第二次epoll_wait()出现40ms延迟,导致吞吐量仅约11kB/s

客户端时间戳日志

[ 1585038.0005] start send 56  
[ 1585038.0006] end send 56  
[ 1585038.0006] start send 512  
[ 1585038.0006] end send 512  

服务端时间戳日志

[ 1585038.0002] epoll_wait 
[ 1585038.0006] start recv 56
[ 1585038.0006] recv return 56
[ 1585038.0006] start recv 512
[ 1585038.0006] recv return -1
[ 1585038.0006] epoll_wait
[ 1585038.0442] epoll_wait return 1
[ 1585038.0443] start recv 512
[ 1585038.0443] recv return 512

原因分析

延迟是Nagle算法与**TCP延迟确认(Delayed ACK)**共同作用的结果:

  1. 客户端发送56字节后,服务端成功接收,但TCP延迟确认机制默认会延迟40ms再发送ACK(Linux系统默认配置)
  2. 客户端发送512字节时,Nagle算法(默认开启)会等待前一包的ACK返回后再发送当前包,导致512字节被暂存
  3. 40ms后服务端发送延迟ACK,客户端才将512字节发出,服务端的epoll_wait()此时才被唤醒,出现明显延迟

解决方法

  • 关闭Nagle算法:在客户端设置socket的TCP_NODELAY选项,让小数据包立即发送,无需等待ACK:
    int flag = 1;
    setsockopt(client_fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
    
  • 合并发送数据:将56字节头部与512字节主体合并为一个缓冲区,一次性调用send()发送,避免触发Nagle算法的等待逻辑
  • 调整ACK时机:服务端在接收头部后,立即通过应用层响应或空包触发ACK发送,避免延迟确认(不推荐修改系统全局TCP参数)

内容的提问来源于stack exchange,提问作者yuanjianpeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:42:39