倚天性能优化—ptg-optimize高性能基础库

本文涉及的产品
云服务器 ECS,每月免费额度200元 3个月
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云服务器ECS,u1 2核4GB 1个月
简介: ptg-optimize为平头哥数据中心解决方案团队开发的一款高性能库,该高性能库借助倚天的硬件架构优势,通过算法设计优化、SIMD向量化、指令优化等,实现包括mem、string、crc32、crypto、spinlock、等20+常用接口的性能优化,mem/string/spinlock等常用接口对标glibc 2.32,crc32/crypto等接口对标业务常用标准化接口。经测试,当前版本优化接口平均性能提升超过50%,性能优化效果显著,集成使用便捷,已为包括集团ebs存储、tair、rds数据库等多种场景提供应用性能加速。

1. 背景介绍

1.1 问题&思考

     由于业务长期在x86架构下进行软件开发,业务侧对x86架构的性能优化有较多经验积累,代码在x86指令集下运行性能良好,当业务由x86切倚天710后,部分热点接口如何与倚天710的硬件能力深度融合、提升热点接口性能来促成业务软件更好的运行在倚天710平台,是当前面临的一个挑战;

     业务对常见热点接口的优化诉求强烈,但是对全量的库升级如(glibc版本升级)保持慎重,我们交流过较多的业务,他们当前的glibc常见接口版本为glibc 2.32,甚至部分还是用glibc 2.17,基于此判断,我们把业务常用的glibc常见接口优化也归划进来,让用户不需要升级glibc版本,就能享受到比最新glibc版本性能更优的接口性能。

1.2 策略

     ptg-optimize为平头哥数据中心解决方案团队开发的一款高性能库,该高性能库借助倚天的硬件架构优势,通过算法设计优化、SIMD向量化、指令优化等,实现包括mem、string、crc32、crypto、spinlock、等20+常用接口的性能优化,mem/string/spinlock等常用接口对标glibc 2.32,crc32/crypto等接口对标业务常用标准化接口。经测试,当前版本优化接口平均性能提升超过50%,性能优化效果显著,集成使用便捷,已为包括集团ebs存储、tair、rds数据库等多种场景提供应用性能加速。

2. 高性能库系统框图

?

网络异常,图片无法展示
|

     如上为高性能库系统框图,绿色部分为已经实现的接口,红色部分为规划待实现的接口,已实现包括glibc 2.32中常见的mem、string等接口10+个,以及CRC32等业务侧常用的标准化接口4+个,crc32_with_memcpy等业务侧定制化接口2+个(业务热点中对同一串inputString先做copy,随后做crc32,平头哥数据中心解决方案团队通过定制优化,将crc32与copy整合在同一个接口中,来实现性能的大幅提升),crypto加解密SM4、AES相关的接口6+个,锁相关的接口6+个。后续我们将继续补齐glibc 2.32常见接口、hash常见接口的优化。

3. 优化接口列表

     优化接口包括如下,后续我们会持续迭代,新增优化接口,如果业务侧在上倚天710过程中有函数热点需要优化,欢迎联系我们,我们将评估需求并规划进版本迭代中:

#define LIBOPTIMIZE_API attribute((visibility("default")))voidptg_memcpy_neon(voiddst, constvoid*src, size_tn);
voidptg_memcpy_less32(voiddst, constvoid*src, size_tn);
voidptg_memcpy_crc32c(voiddst, constvoidsrc, size_tn, uint32_tcrc);
intptg_spin_lock(pthread_spinlock_t*lock);
intptg_spin_unlock(pthread_spinlock_t*lock);
intptg_spin_lock_cas(pthread_spinlock_t*lock);
intptg_spin_unlock_cas(pthread_spinlock_t*lock);
boolptg_atomic32_compare_exchange_n(volatileuint32_tptr, uint32_texpected, uint32_tdesired);
boolptg_atomic64_compare_exchange_n(volatileuint64_tptr, uint64_texpected, uint64_tdesired);
boolptg_atomic32_ldst_compare_exchange_n(volatileuint32_tptr, uint32_texpected, uint32_tdesired);
boolptg_atomic64_ldst_compare_exchange_n(volatileuint64_tptr, uint64_texpected, uint64_tdesired);
/*Polynomial 0x04C11DB7*/uint32_tptg_crc32(uint32_tcrc, constunsignedchar*data, size_tlen);
uint16_tptg_crc16(uint32_tcrc, constunsignedchar*data, size_tlen);
/*Polynomial 0x1EDC6F41*/uint32_tptg_crc32c(uint32_tcrc, constunsignedchar*data, size_tlen);
uint32_tptg_crc32c_with_memcpy(uint32_tcrc, constunsignedchardata, size_tlen, voiddst);
uint16_tptg_crc16c(uint32_tcrc, constunsignedchar*data, size_tlen);
?intptg_memcmp_len20(constvoids1, constvoids2, size_tn);
intptg_memcmp(constvoids1, constvoids2, size_tn);
voidptg_memchr(constvoidbuf, charch, unsignedcount);
voidptg_memrchr(constvoidbuf, charch, unsignedcount);
voidptg_memset(voids, intc, size_tn);
?charptg_strchr(constchars, intc);
charptg_strchrnul(charstr,intc);
intptg_strcmp(constchars1, constchars2);
?externLIBOPTIMIZE_APIintneon_sm4_ctr_encrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
?externLIBOPTIMIZE_APIintneon_sm4_ctr_decrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
?externLIBOPTIMIZE_APIintneon_sm4_cbc_encrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
?externLIBOPTIMIZE_APIintneon_sm4_cbc_decrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
?externLIBOPTIMIZE_APIintneon_aes_xts_encrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
?externLIBOPTIMIZE_APIintneon_aes_xts_decrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
?externLIBOPTIMIZE_APIintneon_aes_ctr_encrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);
?externLIBOPTIMIZE_APIintneon_aes_ctr_decrypt(unsignedchar*input, intinlen,
unsignedcharoutput, intoutlen, unsignedchar*key, intkeylen, unsignedchariv[16]);

4. 如何优化

倚天710基于armv9指令集架构,有如crc、aes、bf16、sve/neon等特性能力,L1、L2  i/dcache等均相比icelake有较大优势,具体特性如下图所示:

?

网络异常,图片无法展示
|
网络异常,图片无法展示
|

我们团队通过对倚天710微架构特性的剖析,基于top-down模型视角,在微指令融合、热点指令重排、访存预取、SIMD向量化(sve/neon)、循环展开、pmul+eor+crc32指令流取代crc32单指令来提升后端ALU吞吐等一些列手段,系统性优化接口性能,使常见接口在倚天710上高效运行。

?

网络异常,图片无法展示
|
网络异常,图片无法展示
|

由于接口较多,我仅选取如下5个接口来说明我们的优化思路及方法,如果读者对其他接口的优化也感兴趣,欢迎钉钉联系我们:

4.1 spinlock接口优化

自旋锁为glibc 2.32中提供了标准接口,该接口为多线程业务提供共享临界区的保护,倚天710单片128core,自旋锁通过对锁的原子操作实现,通过EMSI C2C协议保证数据的有效性,当同一时刻对同一cacheline的monitor监听core数增加时,即同一时刻较多线程在争抢同一个原子变量,会导致系统整体的吞吐性能下降:

?

为了提升多线程抢锁的性能,我们在自旋锁的内部实现上引入了casal以及随机散列算法,来降低同一时刻线程争抢同一原子操作的次数,极大提升了系统的并发性能,在抢锁位置插入随机打散算法,通过争抢失败的次数来作为随机生成变量来等待N个wfe:

测试多线程抢锁数据如下,结果表明,线程越多、争抢越激烈的场景,性能提升越多,提升2-20倍性能;

?

4.2 crc32接口优化

crc32为各个业务常用的标准接口,当前标准接口通过集成通用的crc32指令,可以达到较高的性能收益,但是每个core的crc32硬件引擎只有一个,后端backend成为影响整体吞吐的瓶颈点,我们通过引入eor以及pmul指令来计算crc32,提升了后端ALU引擎的并发使用度,达到了较高的性能收益:

相比标准使用crc32指令的接口,提升后端吞吐后的性能平均提升35%+,如下图所示,对crc32重载的业务有相当大的收益,当前已落地ebs存储业务;

?

4.3 sm4国密接口优化

?

SM4-CTR算法是一种基于SM4分组加密和CTR模式的对称加密算法,具有高效和安全性等优点,因为算法使用的是块加密的CTR模式,可以将固定长度的明文块转换成密文块,CTR模式具有并行处理能力,因此在实际应用中适合大规模数据的加密解密。其加密流程如下:

1. 初始化:选择一个固定长度的计数器nonce和密钥K,并从初始值开始,按照CTR模式进行初始化。

2. 生成密钥流:使用SM4算法加密计数器nonce,产生M-bit的密钥流Keystream(M为SM4短块长度)。

3. 加密:将Keystream和明文异或,生成密文Ciphertext,并更新计数器nonce的值。

4. 重复执行步骤2和3,直至所有明文块加密完成。

在2,3步骤中,在liboptimize库中我们使用armv8 sm4e进行加速,并通过.inst指令转换为机器码,进一步缩减指令数;

优化前后性能数据对比如下图所示,其中rds数据库集成该优化库算法后,端到端提升了加解密场景性能20%,当前已跟rds数据库完成联调测试;

?

4.4 memcpy接口优化

memcpy为各个业务常调用的接口,我们借助sve及neon向量化以及部分指令重排、

cacheline预取,相比glibc 2.32中的memcpy,极大提升了在256Bytes以上的性能;

优化后接口相比glibc 2.32平均提升45%,当前已落地到存储ebs业务中,并与tair业务进行联调中:

?

4.5 ptg_crc32c_with_memcpy接口优化

除了优化标准化接口,我们还会根据业务的实际做定制化优化,如ebs存储业务,他们业务中对crc32的计算负载较大,同时,用来做crc32计算的inputString需要提前做memcpy来获取,基于此场景,我们跟业务方对齐思路,可以在memcpy inputString过程中,就把这串inputString的crc32一并计算出来,可以极大的降低访存延迟:

优化后接口相比客户原先使用crc32+memcpy两次调用方式,可以提升100%的性能,当前已落地至ebs存储业务中:

?


相关文章
|
8月前
|
SQL 存储 算法
ClickHouse性能优化 3
ClickHouse性能优化
279 0
|
11天前
|
存储 缓存 前端开发
《构建高性能的前端应用:优化技巧与最佳实践》
本文探讨了构建高性能前端应用的关键技巧与最佳实践。从代码优化、资源压缩到网络请求管理,提供了一系列有效的解决方案,旨在帮助开发者提升前端应用的性能和用户体验。
|
20天前
|
存储 缓存 JavaScript
性能优化:通用快照方案
本文我们将探讨快照技术如何增强页面性能和用户体验,如何在业务中集成快照方案,以及我们的通用快照解决方案的技术细节。
|
8月前
|
存储 SQL 固态存储
ClickHouse性能优化 2
ClickHouse性能优化
315 0
|
8月前
|
存储 SQL HIVE
ClickHouse性能优化 1
ClickHouse性能优化
155 0
|
9月前
|
编译器 C++ Anolis
性能优化特性之:PGO
本文介绍了倚天实例上的编译优化特性:PGO,并从优化原理、使用方法进行了详细阐述。
|
9月前
|
存储 编译器 C语言
性能优化特性之:LTO
本文介绍了倚天实例上的编译优化特性:LTO,并从优化原理、使用方法进行了详细阐述。
|
10月前
|
存储 缓存 NoSQL
性能优化方案及思考
周末闲暇在家,朋友让我帮忙优化一个接口,这个接口之前每次加载都需要40s左右,经过优化将性能提了10倍左右;又加了缓存直接接口响应目前为300ms左右,于是将自己的优化思路整理总结一下
|
10月前
|
消息中间件 监控 固态存储
榨干服务器:一次惨无人道的性能优化
做过2B类系统的同学都知道,2B系统最恶心的操作就是什么都喜欢批量,这不,我最近就遇到了一个恶心的需求——50个用户同时每人导入1万条单据,每个单据七八十个字段,请给我优化。
|
11月前
|
监控 网络协议 安全
聊聊服务器性能优化~(建议收藏)
聊聊服务器性能优化~(建议收藏)
273 0
http://www.vxiaotou.com