背景
随着计算机技术的蓬勃发展,如今个人计算机已走进千家万户,彻底改变了人们的生活方式。计算机主要由两部分组成,一部分是硬件系统,一部分是软件系统。近几十年来,计算机硬件性能的提升遵循着摩尔定律--每18个月翻一番,而计算机软件也总会适时地吃掉所有性能,并渴望着更高的计算效率。从最初需要穿孔纸或卡片来进行数据的输入输出、使用人工连线来更换程序的计算机发展初期,到如今的人们只需要简单地使用键鼠就能进行各种各样的复杂操作,计算机软件也在一步步的更新换代。从一开始,人们需要使用汇编语言来进行程序编写,到如今众多高级语言的诞生,编程的准入门槛越来越低,各种计算机语言的社区也是一片欣欣向荣,人们拥有了更多的时间来关注他们所要实现的具体业务,而不必困扰于如何进行实现。
如今使用最为广泛的高级编程语言主要以Python、C、Java、C++以及C#为主,下图展示了TIOBE所统计的Top 10编程语言走势。Python以其易用性吸引了越来越多的编程人员,不过鉴于解释型语言的特性,其性能一直为人所诟病。不过,随着版本的更迭,Python开发人员也越来越关注性能上的提升,尤其是最近几个版本的发布,能够明显地看到程序运行效率的提升。近期,Python 3.11正式版发布在即,根据官方数据显示,Python 3.11 比Python 3.10 快 10~60%,基准组件加速了1.22倍。
Top 10 编程语言走势图
在这篇文章中,我们主要对近几个版本进行了性能测评对比,它们分别是3.7,3.8,3.9,3.10以及3.11.0rc1。为了更公平地比较,我们不仅使用了官方提供的pyperformance包进行了基准性能测试,同时还将测评任务与实际业务场景相结合,使用Python重写了阿里云-日志服务(SLS)数据加工任务中的部分算子,在将这些算子进行组合以进行数据加工的场景下进行了不同Python版本的性能测评。
Python性能演变
版本说明
当前,Python 3.11发布在即,官方表示该版本带来了极大的性能提升,在这篇文章中,我们测试了不同Python版本的性能表现,从而为项目中Python版本的升级提供一些参考意见。所测评的Python版本信息如下:
- python 3.7
- python 3.8
- python 3.9
- python 3.10
- python 3.11.0rc1
测试方案
我们在阿里云ECS机器上部署了多个版本的Python,并使用官方提供的pyperformance包进行基准性能测试。pyperformance 项目旨在成为所有 Python 实现基准的权威来源。重点是真实世界的基准测试,而不是综合基准测试,尽可能使用整个应用程序。在运行pyperformance的时候,它会运行一套几十个的基准测试,并对结果进行了统计,降低了开发人员测试的难度。
任务场景介绍
基于pyperformance的性能测评
阿里云服务器(Elastic Compute Service, 简称ECS)是一种安全可靠、弹性可伸缩的云计算服务器,可以帮助公司、组织和个人构建更加安全稳定的应用,降低IT成本,提升运维效率,让相关人员更专注于核心业务的创新。如今,越来越多的应用服务部署于阿里云服务器上,在ECS上测评不同Python版本的性能对于众多的业务场景具有广泛的适用性。测评时所选用的ECS配置如下:
规格 |
2 vCPU 8 GiB (ecs.g7.large) |
I/O优化 |
是 |
系统盘 |
ESSD云盘 40GiB,PL0(单盘IOPS性能上限1万) |
操作系统 |
linux/CentOS 8.5 64位 |
通过官方提供的pyperformance包,我们对不同Python版本的性能进行了测试,所使用的方法为:
python3.* -m pyoerformance run -o python-3.*.json
其中 *
表示Python版本,如7、8、9、10、11。为保证测评的公平性,在测评期间,除了pyperformance以及必要后台程序的运行,未运行其他任何程序。
Python各版本的性能表现
在下表中,我们统计了在ECS上Python高版本相对于Python 3.7的测试性能表现。从表中可以看到,python 3.8、python 3.9以及python 3.10性能相近且相对于python 3.7,性能都只有略微的提升,而到了python 3.11,其性能相对于python 3.7几何均值提高了41%。在性能对比测试的59个项目中,绝大多数情况下,随着版本的升高,性能都有着一定的提升,尤其是对于Python 3.11版本而言相较于Python 3.7,它仅在unpickle_list、scimark_sparse_mat_mult以及python_startup_no_site三个项目上具有略微的性能劣势,而在其他项目上都具有更好的性能表现,甚至在部分项目上,其性能的提升高达百分之百,如raytrace、scimark_sor、logging_silent等项目。
高版本与Python 3.7的性能对比
python 3.7 |
python 3.8 |
python 3.9 |
python 3.10 |
python 3.11.0rc1 |
|
faster num |
-/- |
44/59 |
48/59 |
49/59 |
55/59 |
Geometric mean |
- |
1.05x faster |
1.05 faster |
1.06x faster |
1.41x faster |
Mean |
106 ms |
87 ms |
84 ms |
89 ms |
63 ms |
我们从pyperformance测评的59个项目中选择了其中12个被使用频率较高的项目,然后在这些项目上比较了Python 3.8、Python 3.9、Python 3.10以及Python 3.11相对Python 3.7的性能表现,结果如下图所示,各个标记点表示对应版本在各个项目上的运行速率倍数,距离圆心越远表示性能表现越佳。从图中可以看到,Python 3.8、Python 3.9以及Python 3.10在大部分项目中相对于Python 3.7都有一定的性能提升,不过它们之间并没有明显的性能优势。而Python 3.11在多个项目中,都表现出了超强的性能,甚至在mako项目上,与Python 3.7相比,性能提高超过了百分之百。
模拟SLS数据加工场景
任务场景介绍
数据加工服务是阿里云SLS推出的面向日志ETL处理的服务,主要解决数据加工过程中转换、过滤、分发、富化等场景,其提供了Python语法子集作为用户使用接口。为了在具体业务场景中测试不同Python版本的性能,我们使用Python模拟了客户使用SLS数据加工完成nginx日志解析富化的过程。测评所使用的数据根据模板随机生成,样例如下所示:
bytes_sent:1195cookie_mbparentid:-cookie_mbstudentid:-cookie_parentId:-cookie_studentId:-env_name:alihost:internal.cms-admin.test.com.cnhostname:l-internal-nginx-nginx3.ops.prod.ali.dmhttp_authorization:-http_referer:-http_user_agent:Apache-HttpClient/4.5.13 (Java/1.8.0_212) http_vk_session_id:-http_x_forwarded_for:10.245.79.157http_x_forwarded_proto:httpmsec:1662985712.423remote_addr:100.121.196.108remote_user:-request_method:GETrequest_method_r:GETrequest_protocol:HTTP/1.1request_time:0.008request_trace_id:internal.cms-admin.test.com.cn-6698-144280548015-0-1662985712.415request_trace_seq:0request_uri:/api/service/private/channel/find?id=14767550status:200time_local:12/Sep/2022:20:28:32upstream_addr:10.245.13.126:80upstream_connect_time:0.000upstream_response_time:0.008upstream_status:200
此次模拟的数据加工代码脚本如下:
e_rename( "__raw__", "message", "host", "http_host", "request_uri", "url", "http_x_forwarded_proto", "scheme", ) e_regex("url", "([^?]+)\??.*", ["uri"]) e_set("domain", "nginx") e_set("http_uri", str_format("http://{}{}", v("http_host"), v("uri"))) e_set("http_url", str_format("http://{}{}", v("http_host"), v("url"))) e_if( e_has("time_local"), e_compose( e_set( "source_timestamp", dt_parsetimestamp( dt_strptime(v("time_local"), "%d/%b/%Y:%H:%M:%S"), "Asia/Shanghai" ), ), e_set("__time__", v("source_timestamp")), e_set( "source_date", dt_strftimestamp(v("source_timestamp"), fmt="%Y-%m-%d", tz="Asia/Shanghai"), ), ), ) e_set("source_host", v("__source__")) e_set("time_unit", "second") e_set("upstream_bytes_received", "-") e_set("upstream_bytes_sent", "-") e_set("bytes_received", "-") e_set( "request", str_format("{} {} {}", v("request_method"), v("url"), v("request_protocol")), ) e_regex("__tag__:__path__", r"\S+/(?<project>\S+).log") e_set("topic", str_format("nginx_{}", v("project"))) e_set("http_vk_session_id", v("env_name")) e_set("tmp_str_split", str_split(v("request_trace_id"), "-")) e_set("tmp_arr_len", op_len(json_parse(v("tmp_str_split")))) e_if( op_eq(v("tmp_arr_len"), "6"), e_compose( e_set("productId", lst_get(v("tmp_str_split"), 0)), e_set("userId_hex", lst_get(v("tmp_str_split"), 1)), e_set("appSessionId", lst_get(v("tmp_str_split"), 2)), e_set("pageSessionId", lst_get(v("tmp_str_split"), 3)), e_set("feSessionId", lst_get(v("tmp_str_split"), 4)), e_set("traceId", lst_get(v("tmp_str_split"), 5)), ), ) e_drop_fields( "env_name", "msec", "request_method_r", "request_protocol", "tmp_arr_len", "tmp_str_split", ) e_if( e_search("message:localhost"), e_set("is_localhost", 1), e_search("message:internal"), e_set("is_internal", 1), e_search("message:prod"), e_set("is_prod", 1), )
经过上述数据加工的结果如下所示:
appSessionId:6698bytes_received:-bytes_sent:1195cookie_mbparentid:-cookie_mbstudentid:-cookie_parentId:-cookie_studentId:-domain:nginxfeSessionId:0hostname:l-internal-nginx-nginx3.ops.prod.ali.dmhttp_authorization:-http_host:internal.cms-admin.test.com.cnhttp_referer:-http_uri:http://internal.cms-admin.test.com.cn/api/service/private/channel/findhttp_url:http://internal.cms-admin.test.com.cn/api/service/private/channel/find?id=14767550http_user_agent:Apache-HttpClient/4.5.13 (Java/1.8.0_212) http_vk_session_id:alihttp_x_forwarded_for:10.245.79.157is_internal:1is_prod:1message:12/Sep/2022:20:28:32+0800|l-internal-nginx-nginx3.ops.prod.ali.dm|100.121.196.108|10.245.13.126:80|0.008|0.008|0.000|200|200|-|1195|-|-|-|GET/api/service/private/channel/find?id=14767550HTTP/1.1|Apache-HttpClient/4.5.13 (Java/1.8.0_212)|-|internal.cms-admin.test.com.cn|second|1662985712.423|^_^|http|GET|internal.cms-admin.test.com.cn-6698-144280548015-0-1662985712.415|0|^_^|10.245.79.157|-|-|-|-|-|ali|-pageSessionId:144280548015productId:internal.cmsremote_addr:100.121.196.108remote_user:-request:GET/api/service/private/channel/find?id=14767550HTTP/1.1request_method:GETrequest_time:0.008request_trace_id:internal.cms-admin.test.com.cn-6698-144280548015-0-1662985712.415request_trace_seq:0scheme:httpsource_date:2022-09-12source_host:fan-real-datasource_timestamp:1662985712status:200time_local:12/Sep/2022:20:28:32time_unit:secondtopic:nginx_NonetraceId:1662985712.415upstream_addr:10.245.13.126:80upstream_bytes_received:-upstream_bytes_sent:-upstream_connect_time:0.000upstream_response_time:0.008upstream_status:200uri:/api/service/private/channel/findurl:/api/service/private/channel/find?id=14767550userId_hex:admin.test.com.cn
在数据加工任务上性能对比
使用Python重写的算子构成的数据加工代码对 2,686,599 条数据进行相同的加工处理时,各个Python版本下数据加工效率如下表所示。
python 3.7 |
python 3.9 |
python 3.10 |
python 3.11 |
|
峰值/分钟 |
3.71 k |
3.90 k |
4.20 k |
4.77 k |
八分钟 |
1.72 Mil |
1.74 Mil |
1.81 Mil |
2.06 Mil |
从表中可以看到,随着python版本的升高,加工效率均有不同程度的提升,其中Python 3.9相对于Python 3.7的数据处理速度提高了大约1.16%,Python 3.10相对于Python 3.7性能提高了大约5.23%,而Python 3.11相对于Python 3.7的加工性能提高了大约19.77%,如此大幅的性能增强将带来对应的效率提升。
下图展示了在一次作业运行过程中,处理等量数据的情况下,各Python版本对于日志的处理速度。从图中可以看到,在该任务场景下Python 3.11的性能相较于其他版本具有明显的优势。首先是在启动速度方面,Python 3.11能够在更短的时间内启动并更快的达到最高的数据处理水平。与其他版本性能差距较小导致数据处理速度曲线纠缠在一起不同,Python 3.11版本的性能曲线与其他版本明显区隔开,可见性能优势较大。从中可以得到结论,在该业务场景下,无论是对少量数据进行处理的短时任务,还是对大量数据进行处理的长时任务,Python 3.11相较于其他版本均具有明显的性能优势。
结论
通过在两个任务场景上进行详细的性能测试,我们可以看到,Python 3.11确实如官方所言,在性能方面有了极大的提高。而在具体的业务场景--阿里云-日志服务(SLS)数据加工任务之上,Python 3.11的性能相较于Python 3.7提高了 20%左右。这意味着,在不改变其他条件的情况下,仅通过版本升级,就能给我们带来较大的效能提升。
附录
基于pyperformance的不同Python版本在ECS上性能对比表
python 3.7 |
python 3.8 |
python 3.9 |
python 3.10 |
python 3.11 |
|
crypto_pyaes |
133 ms |
128 ms |
121 ms |
126 ms |
77 ms |
django_template |
69.3 ms |
58.6 ms |
59.6 ms |
58.2 ms |
38.3 ms |
float |
131 ms |
139 ms |
134 ms |
120 ms |
78 ms |
json_dumps |
14.9 ms |
14.6 ms |
14.4 ms |
14.3 ms |
13.1 ms |
mako |
21.5 ms |
19.8 ms |
18.4 ms |
17.3 ms |
10.6 ms |
nqueens |
121 ms |
117 ms |
112 ms |
115 ms |
97 ms |
python_startup |
10.3 ms |
12.1 ms |
10.5 ms |
10.5 ms |
9.8 ms |
regex_compile |
213 ms |
197 ms |
200 ms |
202 ms |
148 ms |
spectral_norm |
144 ms |
151 ms |
152 ms |
159 ms |
101 ms |
xml_etree_process |
106 ms |
87 ms |
84 ms |
89 ms |
63 ms |
Mean |
96.4 ms |
92.4 ms |
90.6 ms |
91.1 ms |
63.6 ms |