春节运动排行榜性能优化小记

春节初一~初三期间,红包活动页左上角会有春节排行榜的入口,前期预估峰值:15w/s。

排行榜server优化前后数据对比如下(备注:以下数据,均假设从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,
  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天左右。


参考资料

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


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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • 特别说明: 1、本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识...
    安易学车阅读 1,809评论 0 40
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,236评论 11 349
  • TITLE: 编程语言乱炖 码农最大的烦恼——编程语言太多。不是我不学习,这世界变化快! 有时候还是蛮怀念十几、二...
    码园老农阅读 5,316评论 2 35
  • 雨还在下 像在说话 下雨了-薛之谦 喜欢雨天 听着窗外 ...
    七屿PHOTO阅读 260评论 4 9
  • 昨晚关注了一个小姐姐的公众号,然后小姐姐后台回复说,你的名字很好听呢,我这才想起来,貌似我这个微信昵称从注册...
    方依然阅读 3,254评论 0 0