比较不同语言如何处理网络I/O,检查Rust是否保持其高性能的承诺
Eugene Retunsky 6分钟阅读
这篇文章是《衡量网络服务性能》的延续。
当我的电脑没有互联网连接时,我发现我可以用它做的事情不多。事实上,我们大多使用笔记本电脑和智能手机来访问存储或产生于其他地方的信息。甚至很难想象,如果没有网络通信,非面向用户的应用程序的效用。虽然I/O操作与数据处理的比例可能不同,但这种操作对服务的延迟的贡献很可能是实实在在的。
有许多编程语言用于实现后端服务。正因为如此,人们对比较这些语言的性能有着天然的兴趣,而且有各种基准。例如,有Benchmarks Game,它比较了不同语言解决不同的离线任务。另一套基准,TechEmpower,测量网络框架的性能。这些测量是很有用的,可以对语言的性能能力有一个大致的了解。然而,它们通常是测量一些特定的用例和操作集,这不一定具有代表性。
所有这些都让我对不同平台上裸露的I/O的不可减少的成本感到好奇。对TCP代理的基准测试可能是最简单的情况。没有数据处理,只是处理传入/传出连接和转发原始字节数据。微服务几乎不可能比TCP代理更快,因为它不能做得更少。它只能做得更多。任何其他功能都是建立在这个基础上的--解析、验证、遍历、打包、计算等等。
目前正在比较以下解决方案。
上述所有的解决方案都使用非阻塞式I/O。在我之前的文章中,我试图说服读者,如果你需要低延迟和大吞吐量的高可用服务,这是处理网络通信的最佳方式。
简单说明一下--我试图在Golang、Java和Python中挑选最好的解决方案,但如果你知道有更好的替代品,请随时联系我。
实际的后端是Nginx,它被配置为在HTTP模式下提供10kb的数据。
基准结果被分成两组。
是的,Rust属于两个世界。
方法的简要描述
我们将比较以下统计数据。
请随时了解更多关于方法和为什么选择这些统计数字的信息。为了收集数据,我使用了perf-gauge。
好吧,让我们来谈谈结果吧!
我经常听说Rust在性能方面与C/C++不相上下。让我们来看看在处理网络I/O方面,'不相上下 '到底意味着什么。
请看下面的四张图,顺序如下。基线、C、C++、Rust。
绿色-p50,黄色-p90,蓝色-p99,单位为µs(在左边)。橙色-速率(在右边
下面,你会看到每个统计数字在后台的基础上增加了多少微秒。下面的数字是在最大请求率下的时间间隔的平均值(不包括爬升的时间)。
开销,µs
相对而言(管理费占基线的百分比)。
间接费用占基线统计的%。
有趣的是,虽然用C++编写的代理在p99.9级别上比HAProxy和Rust都要快一点,但在p99.99和最大级别上却更差。然而,这可能是一个实现的属性,在这里是非常基本的(通过回调实现,而不是处理期货)。
此外,还测量了CPU和内存消耗。你可以在这里看到这些。
总之,用C、C++和Rust编写的所有三个TCP代理都表现出类似的性能:精简和稳定。
现在,我们来比较一下内存安全的语言。不幸的是,Java和Python的解决方案无法在仅有的两个核心上处理25,000 rps,因此Java以15,000 rps为基准,Python以10,000 rps为基准进行测试。
请看下面四张图,顺序如下。Rust, Golang, Java, Python。
绿色-p50,黄色-p90,蓝色-p99,单位为µs(在左边)。橙色-速率(在右边
那么,现在我们看到了一个巨大的差异。在以前的图表中,在新的比例中,Rust似乎很稳定。另外,注意到Java的冷启动峰值。下面的数字是在最大请求率下的间隔的平均值(不包括上升期)。
开销,µs
正如你所看到的,Golang在p50/p90水平上有一定的可比性。然而,在更高的百分位数上,差异会急剧增长,这一点从标准差中可以看出。但是,看看Java的数字吧!
值得一看的是离群(p99.9和p99.99)的百分位数。很容易看出,与Rust的差异是巨大的。
绿色--p99.9,蓝色--p99.99,单位是μs(在左边)。橙色 - 速率(在右边
相对而言(与基线Nginx的百分比)。
间接费用占基线统计的%。
总之,Rust的延迟差异比Golang、Python,尤其是Java低得多。Golang在p50/p90延迟水平上与Rust相当。
另一个有趣的问题--每个代理能够处理的最大请求率是多少?同样,你可以阅读完整的基准以获得更多信息,但现在,这里是一个简短的总结。
Nginx能够处理60,000rps多一点的数据。如果我们在客户端和后端之间放一个TCP代理,会降低吞吐量。正如你在下面看到的,C、C++、Rust和Golang达到了Nginx直接服务的70%-80%左右,而Java和Python表现更差。
左轴:延时开销。右轴:吞吐量
这些基准并不全面,目的是为了比较不同语言的裸露I/O。
然而,与Benchmarks Game和TechEmpower一起,他们表明,如果可预测的性能对你的服务至关重要,那么Rust可能是Golang、Java或Python的更好选择。另外,在开始用C或C++编写一个新的服务之前,值得考虑Rust。因为它的性能和C/C++一样,而且在此基础上。
联系客服