chenshuo / muduo

Event-driven network library for multi-threaded Linux server in C++11
https://github.com/chenshuo/muduo
Other
14.85k stars 5.17k forks source link

EventLoop::wakeup() 耗时时不时很大 #474

Closed seudut closed 3 years ago

seudut commented 4 years ago

我发现在 调 EventLoop::queueInLoop(), 有时候耗时会特别大(20-30ms),特别是在其它线程调用 loop 的时候。 通过打时间戳,发现耗时都在 EventLoop::wakeup() 这个函数 里的 socket::write()上。一般情况下,这个write 是 10us 级别的,但是时不时的会突然变到 30ms。我的机器是 debian linux 8 核,16G ram

请问一下,这大概是什么原因导致在写 eventfd 时耗时会增大?有什么可以改进措施的吗?

Linux distro and version? x86 or ARM? 32-bit or 64-bit?

64bit 8 core 16G ram, debian Linux 9

Branch (cpp98/cpp11/cpp17) and version of muduo?

cpp11

Version of cmake, gcc and boost? (If not from distro.)

cmake 3.7

chenshuo commented 4 years ago

如果这造成困扰,可以试试把 eventfd 换成普通 pipe,看看是否解决。具体做法可参考 muduo/patches/backport.diff 中对 EventLoop.{h,cc} 的改动。

seudut commented 4 years ago

谢谢! 我按你说的试了socketpair, pipe 的方法。是有些改善,耗时大的次数有些减少。但是最大耗时的值没有减小。我后来也做过简单测试,只是调一个 write() 系统函数,跑的次数多了也一样会出现这个耗时大(20-30ms)的问题。所以这可能和 muduo 的使用没关系,可能是系统调度的限制。现在我的做法是尽量减少 wakeup 调的次数少。不知道有没有什么好的方法?

另外,我也发现在 queueInQueue() 的调度在其它地方也偶尔会有耗时。在 pendingFunctors_.pushback(),偶尔会花30ms 左右。我查过些,说是在 std::function 会有些性能损耗。这方面有什么建议吗?

chenyahui commented 4 years ago

@seudut 会不会是在lambda里面有拷贝参数?

seudut commented 4 years ago

我代码中 lambda 的捕获列表,很少。我试过 std::function, 赋值 =, 和 std::move(), 都有耗时情况,但这这个耗时也不是每次出现,只是偶尔,所以不确定是不是在拷贝参数,还是在构造,析构。另外 std::function()swap() 没有发现这样的耗时情况。

chenshuo commented 4 years ago

30ms 这个数字太大了,你用的是什么硬件平台?是不是虚拟机?时钟有没有跳变?

seudut commented 4 years ago

我用的是aliyun 的服务器,32Core 2.5GHz 的 Debian Linux。 @chenshuo

chenshuo commented 4 years ago

虚拟机的话就可以理解了,但我也没有什么解决办法。建议在物理机器(哪怕是台式机或者 ARM 开发板,不必是服务器)上测试一下,或者用 AWS、Azure、Google Clould 对比一下。

lilothar commented 4 years ago

可以加一个小优化,判断队列是否大于1,大于1情况可以不wakeup