专栏首页鹅厂少年的奇妙之旅【2018手Q春节红包系列】春节排行榜性能优化小记
原创

【2018手Q春节红包系列】春节排行榜性能优化小记

优化后QPS如下图:

春节初一~初三期间,红包活动页右上角会有春节排行榜的入口。

排行榜页面前期预估峰值:15w/s,页面逻辑展示如下:

此次优化前后,排行榜server单机QPS对比如下(备注:以下数据,均假设从CKV中拿到数据,忽略掉oidb相关逻辑):

测试条件:CPU占比不超过85%,超时时间不超过900ms

优化前单机QPS

优化后单机QPS

获取排行榜首页数据(实时拉取好友步数并进行排序)

2200

5200 ( +3000)

获取排行榜分页数据(从Redis快照中直接获取数据)

3000

5500 ( +2500)

用户点赞

12000

12000

发送C2C消息

12000

12000

针对春节排行榜运动侧准备了120台V8机器。以排行榜首页为例,优化前,系统QPS(极限值) = 2200*120 = 26.4w/s,优化后,系统QPS(极限值) = 5200*120 = 62.4w/s提升136.4%。

以CPU占比75%平稳运行而言,系统QPS = 4700*120 = 56.4w/s,此时平均每个请求从发包到收包耗时约40ms

所有接口中,由于排行榜首页,做的逻辑更多更复杂,因此,不出意外,首页QPS是最低的。另外,春节期间排行榜所有请求中,首页的请求应该是最多的,毕竟,用户进入页面首先就会请求首页数据。

综上所述,优化排行榜首页性能成为了整个系统的关键所在。这次优化,也是根据这条思路进行的,下面简要介绍下优化的思路和过程。

一、排行榜逻辑架构图

考虑到公司安全规范,架构图隐去。

要点如下:

1. 存储:主要采用CKV,高性能Kv存储。

2. 外部接口:能异步就异步(除oidb查会员标记位外)

3. 框架:SPP微线程,相关网络操作均采用异步。

4. 备注:SSO寻址走hash一致性寻址,server本地采用Redis做快照,防止排名错乱的问题。

二、压测数据

工欲善其事,必先利其器。这里不得不提到test.server.com这个压测利器,文中所有数据和结果均来自test.server.com提供的压测客户端。有兴趣的同学参见此文

优化的步骤无外乎:

A. 压测得到当前Server性能(CPU不超过80%,延迟不超过900ms)

B. Perf查看CPU消耗点在哪里(因为排行榜这里是CPU Bound型)

C. 针对B的结果相应优化,再重复进行步骤A。

1. 原始压测数据(未做优化前):压测到2200/s时,CPU占比已经飙升至80%。

此时,Perf出来的火焰图如下(图为搜索JSON匹配后的结果):

分析后得知,Server中的Json和map的相关操作吃了很大一部分CPU,约占用30%左右。

2. 优化map操作,将代码中所有涉及到map的逻辑全部替换为hash_map和vector。思路:map底层采用RB_Tree的方式实现,查找复杂度为OLog(n);hash_map底层采用Hash_table实现,查找复杂度为O(1)。

优化前QPS

优化后QPS

优化措施

2200

3200 (+1000)

hash_map和vector替换map操作

备注:C99里面的hash_map,不是标准库,是gcc实现的:__gnu_cxx::hash_map。这里性能提升明显,主要是获取步数数据、用户关系链数据及相互匹配时,查找操作较多。

优化后Perf图如下(搜索关键字<map>如下图,CPU占比11%左右):

右图中,之所以map匹配CPU占比超过11%,因为Json相关的操作中大量的使用了map,而Json还没有进行优化。搜索hash_map,CPU占比只有5%左右

3. 优化Json操作。思路:将Json库替换为简单字符串拼接(这里由于是和前端交互,限定了只能使用json交互,因此优化的思路还是从组装json方面考虑,而不是替换为二进制协议,例如pb等)。

优化前QPS

优化后QPS

优化措施

3200

4000 ( +800)

json组装,改为自己拼接字符串

优化后Perf图如右下(搜索关键字<ssdasn::>后如下图):

右图中,可以看到,优化完成后,占用CPU最多的已经变为ssdasn::的相关操作,这些操作是CKV存储的编解码封装,也就是说,后续的性能优化已经和业务无关了。

此时CPU使用如下,占比约80%左右:

4. 减少日志流水操作。思路:忽略正常处理的请求,只打印出错请求处理日志。

优化前QPS

优化后QPS

优化措施

4000

4500 ( +500)

减少日志打印,只打印出错日志

优化前后perf图对比如下:

左图为优化前,日志流水操作占比: 2.08%;右图为优化后,正常情况下日志流水操作占比0%(只有出错才打)。留出了更多的CPU时间给业务逻辑,优化后QPS如下:

5. gcc编译增加O2选项。思路:利用编译器自身的编译优化选项,从编译执行的底层尝试优化性能(业务无关)

优化前QPS

优化后QPS

优化措施

4500

5200 ( +700)

使用gcc O2优化选项

优化后QPS如下图:

此时,业务server等待队列耗时如下,可以看到,请求基本都在server收到包后1ms内开始被处理,不会堆积:

CPU占比如下,约占比85%左右:

三、走过的弯路

在初步压测出单机QPS=2200后,由于缺乏经验,没有从火焰图去分析CPU到底消耗在哪里。因此只能尝试各种经验上的方法进行优化,例如:

1. 去掉同步快照操作(伤害用户体验)

2. 去掉关系链CKV同步操作(更换成本高)

3. 调整批量获取CKV的数量(经验值)

4. 调大进程数

5. 关闭系统日志

6. 关闭排序(排行榜基础功能)

等...

这些效果都不明显,提升作用有效,最多的时候,有损体验的前提下,QPS才提升到2500左右。

后面在查阅相关资料后,系统化的使用perf、火焰图等工具进行分析,抓到性能瓶颈后,有的放矢,才能在后面的优化过程中,有效的提升系统QPS。

这次优化,从接触学习压测工具开始,到昨天优化告一段落,断断续续持续了有3、4天左右。感谢团长、双太、drog、温总在优化过程中提供的帮助和建议!!!


 参考资料

gcc 编译优化选项O2相关知识,可以参考这篇文章GCC中-O1 -O2 -O3 优化的原理

另外,O2选项优化打开时,注意另外一个选项:-fno-strict-aliasing,如果没有配合使用的话,程序可能产生未定义的行为,大意是说O2选项默认认为不同类型的指针不能指向同一片内存区,如果业务代码中,有强制类型转换,需要注意下这里。具体参考:gcc 编译参数 -fno-strict-aliasing

官方说明在此:Options That Control Optimization

我的理解:O2性能优化选项打开前后代码语义必然相同,最主要的性能优化点,可能还是:未打开前,Gcc编译生成的代码是独立的,每一行代码都可以打断,方便调试;打开后,Gcc编译生成的代码是相关的,并根据一些相关性进行了优化,当然这时候,调试的难度就很大了。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • MySQL索引背后的数据结构及算法原理

    本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题。特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MyS...

    后台搬砖鹅
  • perf + 火焰图分析程序性能

    性能调优时,我们通常需要分析查找到程序百分比高的热点代码片段,这便需要使用 perf record 记录单个函数级别的统计信息,并使用 perf report ...

    后台搬砖鹅
  • 【春节红包系列】一次"内存泄漏"引发的血案

    2017年末,手Q春节红包项目期间,为保障活动期间服务正常稳定,我对性能不佳的Ark Server进行了改造和重写。重编发布一段时间后,结果发现新发布的Svr的...

    后台搬砖鹅
  • DBA大牛告诉你,如何让MySQL语句执行加速?

    like模糊查询形如'%AAA%'和'%AAA'将不会使用索引,但是业务上不可避免可能又需要使用到这种形式。

    lyb-geek
  • DBA大牛告诉你,如何让MySQL语句执行加速?

    like模糊查询形如'%AAA%'和'%AAA'将不会使用索引,但是业务上不可避免可能又需要使用到这种形式。

    程序员追风
  • Intel多核培训感想

             今天是参加Intel多核和多线程培训的第一天,感触颇深。因为目前我们正在开发一个分布式的多线程系统,前不久也做过一些优化,听了今天的课程,能产...

    ternturing
  • 推荐一个在线接口Mock工具fastmock

    上面的方式中,不管哪一种方式,都会要求开发人员写一些跟项目本无任何关联的代码,第一个和第二个方式还会需要前端项目在本地引入不必要的js文件。比如下面的mock数...

    用户4361151
  • Xshell 用 SSH 密钥登录服务器的配置过程

    魏艾斯博客www.vpsss.net
  • 海绵宝宝也懂的HTTPS

    https是建立在SSL(Secure Sockets Layer 安全套接层)上的网络安全协议,最初由NetScape公司提出,之后由IETF标准化为TLS(...

    我就是马云飞
  • poj----Ubiquitous Religions

    Ubiquitous Religions Time Limit: 5000MS Memory Limit: 65536K Total Submi...

    Gxjun

扫码关注云+社区

领取腾讯云代金券