cyanray / mirai-cpp

本项目为 mirai-api-http 的 C++ 封装,方便使用 C++ 开发基于 mirai-api-http 插件。
GNU Affero General Public License v3.0
148 stars 38 forks source link

最新版本代码CPU占用率高 #69

Closed Slontia closed 3 years ago

Slontia commented 3 years ago

背景:最近自己编写的机器人,运行若干分钟后,消息回复延迟十分严重,可能要几小时才能收到回答

分支:master commit hash:6051ea2b65f93

跑的是mirai-cpp-template的示例程序

top命令看到的情况(CentOS8,单核,2GB内存): image

perf命令看到的结果: image

cyanray commented 3 years ago

EDIT: 这是错误的解决方案,正确的解决方案在下面👇

呀…… 这个BUG是因为WebScoket库的select函数的超时时间设置的太小了。

临时解决方法: 把这一行

tv.tv_usec = 20 * 1000;

改成

tv.tv_usec = 200 * 1000;

在wsl上测试了一下,有明显改善。

Slontia commented 3 years ago

呀…… 这个BUG是因为WebScoket库的select函数的超时时间设置的太小了。

临时解决方法: 把这一行

tv.tv_usec = 20 * 1000;

改成

tv.tv_usec = 200 * 1000;

在wsl上测试了一下,有明显改善。

十分感谢您的回复,但我这边似乎似乎并没能生效。我后面又尝试把tv.tv_sec改成20和200,发现这个数字只是延迟了CPU打满的时间,但20s和200s一过,CPU利用率还是飙升到了90+%。

通过perf看了CPU打满时,修改tv.tv_sec前后的变化,发现没有明显差异: image

cyanray commented 3 years ago

呀…… 这个BUG是因为WebScoket库的select函数的超时时间设置的太小了。 临时解决方法: 把这一行

tv.tv_usec = 20 * 1000;

改成

tv.tv_usec = 200 * 1000;

在wsl上测试了一下,有明显改善。

十分感谢您的回复,但我这边似乎似乎并没能生效。我后面又尝试把tv.tv_sec改成20和200,发现这个数字只是延迟了CPU打满的时间,但20s和200s一过,CPU利用率还是飙升到了90+%。

通过perf看了CPU打满时,修改tv.tv_sec前后的变化,发现没有明显差异: image

需要完全清理cmake缓存再重新编译,因为这个文件的改动可能不会被cmake发现。

cyanray commented 3 years ago

sorry, 还真的没有任何改变。 我再仔细研究下……

cyanray commented 3 years ago

select 函数的超时时间用 struct timeval 来表示。 而且 select 函数有可能会修改这个 timeval 的值。(这个应该是看操作系统的,Windows 好像没这个情况) 所以正确的做法是在调用 select 函数之前,初始化 struct timeval

修改后的 WebSocketClient.cpp 应该差不多是这样:

......
struct timeval tv;
-tv.tv_sec = 0;
-tv.tv_usec = 200 * 1000;
while (status == Status::Open)
{
+   tv.tv_sec = 0;
+   tv.tv_usec = 200 * 1000;
    FD_SET(sock, &fds_read);
    int ret = select((int)(sock + 1), &fds_read, NULL, NULL, &tv);
    if (ret < 0)
......

希望这个就是最终答案🤔

cyanray commented 3 years ago

😵消息回复延迟十分严重可能是因为另一个BUG #70

Slontia commented 3 years ago

感谢!目前我这边测试,CPU占用高和消息延时的问题都解决了~