行业报告 AI展会 数据标注 标注供求
数据标注数据集
主页 > 数据挖掘 > 正文

底层I/O性能大PK:Python/Java被碾压,Rust有望取代

我发现一旦计算机没了互联网,我就无所事事。大多数时候,我们都使用笔记本电脑和智能手机访问其他地方存储或生成的信息。我们很难想象如果没有了网络通信,不面向用户的应用还有什么用处。尽管I/O操作与数据处理的比例可能有所不同,但此类操作可能会引发服务延迟。
 
实现后端服务的编程语言有许多。因此,人们对于比较这些语言的性能有着一种天然的好奇心,而比较的基准也各种各样。例如,有一个基准可以比较不同语言在解决不同的离线任务时的性能。还有一个基准TechEmpower,可以衡量Web框架的性能。这些度量非常实用,我们可以通过它们大致了解语言的性能。然而,一般这些基准都有特定的使用场合和特定的操作,所以不一定具有代表性。
 
因此,我对各个平台上基本I/O的不可降低的成本非常好奇。对TCP代理进行基准测试可能是最简单的情况。其中不涉及数据处理,只处理传入/传出连接,并中继原始的字节数据。微服务的速度基本上不可能比TCP代理更快,因为微服务所需做的处理不可能少于TCP代理,它的功能只会更多,比如在此基础上构建的其他功能:解析、验证、遍历、打包、计算等等。
 
在本文中,我们将比较以下解决方案:
HAProxy:TCP代理模式。这是一个使用C语言编写的成熟解决方案。http://www.haproxy.org/
 
draft-http-tunnel:一个使用C++的解决方案(以TCP模式运行),只有最基本的功能(trantor):https://github.com/cmello/draft-http-tunnel/(
 
http-tunnel:使用Rust(tokio)编写的简单的HTTP隧道 / TCP代理(在TCP模式下运行):https://github.com/xnuter/http-tunnel/
 
tcp-proxy:Golang解决方案:https://github.com/jpillora/go-tcp-proxy
 
NetCrusher:解决方案(Java NIO)。使用G1在JDK 11上运行基准测试:https://github.com/NetCrusherOrg/NetCrusher-java/
 
pproxy:基于asyncio的Python解决方案(以TCP代理模式运行):https://pypi.org/project/pproxy/
 
以上所有的解决方案均使用非阻塞I / O。
 
注意:我尽力挑选了Golang、Java和Python的较佳解决方案,如果你知道更好的解决方案,请在下方留言。
 
实际的后端是Nginx,具体配置为:以HTTP模式发送10kb的数据。
 
基准结果分为两组:
基准、C、C++、Rust:高性能语言。
 
Rust、Golang、Java、Python:内存安全的语言。
 
没错,两组中都包含Rust。
 
方法的简要说明
为TCP代理分配了两个核心(使用cpuset)。
 
为后端分配了两个核心(Nginx)。
 
请求速率从10k开始,较高至每秒25k请求。
 
每50个请求共用一个连接(每个请求10kb)。
 
测试在同一台虚拟机上运行,为的是避免网络噪音。
 
VM选择了针对计算优化的实例类型(独占所有分配到的CPU),为的是避免出现“嘈杂的邻居”问题。
 
延迟测量分辨率为微秒(μs)。
 
我们比较的统计数据包括:
百分位数(从p50到p99):关键统计数据。
 
离群值(p99.9和p99.99):对于大型的组件非常关键。
 
较大延迟:最坏的情况永远不容忽视。
 
修整后的均值tm99.9:去除0.1%的较佳/最差值后得到的均值,为的是捕捉中心趋势(不考虑离群值)。
 
标准偏差:评估延迟的稳定性。
 
为了收集数据,我使用了perf-gauge。
 
下面,我们来看看结果!
 
高性能语言:C、C++、Rust
我经常听人说,Rust的性能可与C / C ++媲美。下面我们就来看一看在处理网络I/O时,Rust是否能够表现出同等的水平。 
 
以下四个图分别是:基准、C、C++、Rust:
 

 

图:绿色:p50;黄色:p90;蓝色:p99(以μs为单位)(左图);橙色-速率(右图)
 
将每个统计信息的后端也加上去,所得到的微秒数如下所示。以下数字是在较大请求速率下间隔的平均值(不包括加速):
 

 

图:开销(微秒)
 
相对结果(开销占基准的百分比):
 

 

图:基准统计的开销(%)
 
有趣的是,尽管在p99.9级别上,用C++编写的代理比HAProxy和Rust都快一点,但在p99.99和max上的表现却最糟。但这可能是由于实现导致的,在这里是非常基本的(而且通过回调实现,没有通过处理future实现)。
 
此外,我测量了CPU和内存消耗,详情请看这里(https://github.com/xnuter/perf-gauge/wiki/Moderate-request-rate#cpu-and-memory-consumption)。
 
总的来说,使用C、C++和Rust编写的三个TCP代理表现出的性能不相上下:精简且稳定。
 
比较内存安全语言:Rust、Golang、Java和Python
下面,我们来比较一下内存安全语言。不幸的是,Java和Python的解决方案无法仅通过两个核心处理25,000 rps,因此Java的基准测试为15,000 rps,而Python的基准测试为10,000 rps。
 
下列四个图分别是:Rust、Golang、Java和Python。
 

 

图:绿色:p50;黄色:p90;蓝色:p99(以μs为单位)(左图);橙色-速率(右图)
 
我们看到了巨大的差异。对于Rust,上一张图中的“噪声”似乎很多,但在这张图中非常稳定。另外,请注意Java的冷启动高峰。以下数字是在较大请求速率下间隔的平均值(不包括加速):
 

 

如你所见,Golang在p50 / p90级别上也具备一定的竞争力。但是,在更高的百分位上,差异急剧增加,标准偏差充分反映了这一点。但是,请再看一下Java的数字!
 
离群值(p99.9和p99.99)百分位非常耐人寻味。与Rust的差异肉眼可见:
 

 

图:绿色:p99.9;蓝色:p99.99(μs)(左图);橙色-速率(右图)
 
相对结果(开销占基准的百分比):
 

 

图:基准统计的开销(%)
 
总的来看,Rust的延迟差异远低于Golang、Python,尤其是Java。在p50 / p90的延迟级别上, Golang可与Rust并肩。
 
较大吞吐量
还有一个问题:每个代理可以处理的较大请求速率是多少?
 
Nginx能够处理的请求量超过60,000 rps。如果我们在客户端和后端之间建立一个代理,就会降低吞吐量。如下所示,C、C ++、Rust和Golang服务的请求量可以达到Nginx的70%~80%,而Java和Python的表现则比较差:
 

 

图:左轴:延迟开销;右轴:吞吐量
 
蓝线是tail延迟(Y轴在左侧):越低越好。
 
灰色代表吞吐量(Y轴在右侧):越高越好。
 
总结
这些基准测试并不全面,我的目标是比较各个语言基本的I / O。
 
根据以上测试结果,再结合Benchmarks Game和TechEmpower的结果表明,如果性能对你的服务来说非常重要,那么与Golang、Java或Python相比,Rust可能是更好的替代方案。另外,在使用C或C++编写新服务之前,可以考虑一下Rust。因为Rust不仅具有可与C / C++同等出色的性能,而且还具备以下优势:
 
内存安全。
 
无数据竞争。
 
易于编写方便理解的代码。
 
与Python一样易于访问和灵活。
 
它会迫使工程师在投入生产之前,提前设计和理解数据的所有权。
 
它有一个了不起的社区和一个庞大的组件库。
 
所有试过的人都说好!
 
原文链接:https://medium.com/star-gazers/benchmarking-low-level-i-o-c-c-rust-golang-java-python-9a0d505f85f7
 
声明:文章收集于网络,版权归原作者所有,为传播信息而发,如有侵权,请联系小编删除,谢谢!
 
 

微信公众号

声明:本站部分作品是由网友自主投稿和发布、编辑整理上传,对此类作品本站仅提供交流平台,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,不为其版权负责。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。

网友评论:

发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
SEM推广服务

Copyright©2005-2026 Sykv.com 可思数据 版权所有    京ICP备14056871号

关于我们   免责声明   广告合作   版权声明   联系我们   原创投稿   网站地图  

可思数据 数据标注行业联盟

扫码入群
扫码关注

微信公众号

返回顶部