ROOT
ROOT

C++20 协程特性性能测试

最近用 C++20 写了一个模仿 Python asyncio 的协程库https://github.com/netcan/asyncio,使用方式基本和 Python 一模一样,简单看一下使用方式,例如一个 Hello World:

Task<> hello_world() {
    fmt::print("hello\n");
    co_await asyncio::sleep(1s);
    fmt::print("world\n");
}

int main() {
    asyncio::run(hello_world());
}

编写这个库的目的是为了我 即将出版的 C++20 书籍有关,目前还差协程和 Modules 特性没写,这篇文章不会涉及太多技术细节。很多人关注 C++ 协程的性能表现,据我测试恢复、挂起一个协程和函数开销差不多,大概 10 纳秒的量级,如果使用协程做异步编程,那么这部分开销几乎可以忽略不计,因为 IO 非常耗时,量级通常是毫秒的。

实践出真知,数据才能说明问题,我简单使用这个库和 Python asyncio、C++ 的 asio、C 的 epoll/libevent/libuv、Rust 的 tokio 进行性能测试,通过它们编写一个 单线程 的 Echo 服务端,客户端连接服务端后,发送一条消息立即收到一条发送过的消息。

测试系统为 Debian Linux 5.15.0-1-amd64,CPU 为 AMD 2600X,测试工具为 ApacheBench,消息条数为 10’000’000,每条消息的大小为 106 字节,并发连接数量为 1000,保持长连接测试。由于我没有多余的机器,因此使用本地回环测试,并且使用 C 语言版本作为基线对比。得到如下测试结果:

framework RPS [#/sec] (mean) Language Pattern
python asyncio 47393.59 Python coroutine
this project 164457.63 C++20 coroutine
asio 159322.66 C++20 coroutine
tokio-rs 156852.70 Rust1.59.0-nightly coroutine
epoll 153147.79 C eventloop
libevent 136996.46 C callback
libuv 159937.73 C callback

基本可以看到,C++ 的协程性能是 Python 协程的 3 倍多,当然测试也有波动性,RPS 误差在 5000 左右,所以其他性能基本差不多,就 C 语言版本而言,协程的可读性要比回调模式要好很多,而又不会带来性能上的损耗。

详细的测试代码、数据请参见:https://github.com/netcan/asyncio/blob/master/docs/benchmark.md

相关的技术讨论,整理至FAQ,也可以参考我在 Reddit 发的帖子:

支持一下
扫一扫,支持Netcan
  • 微信扫一扫
  • 支付宝扫一扫