线上模块XX 在高QPS下耗时剧增的原因排查总结

1、确定问题原因:
1)场景复现:方式1:根据现场日志确定问题原因;方式2:压测复现。
存在的问题:方式1:日志中没有保存现场;方式2:压测可能与线上不符;压测可能无法满足某些特殊条件。
2)一些手段:
a.如果问题只在特定机器出现,确定机器硬件配置是否相同,cpu、meminfo、系统配置等;
b.分阶段、逐步细化各步骤的处理时间、队列积压长度等;
c.可以使用一些辅助性能分析工具进行分析,代价是学习成本,场景不一定符合性能分析工具作用的发挥。
最终发现的高qps时,耗时主要集中在信息流配图阶段和it_proc特征收集阶段。

图片描述
图片描述
图片描述
图片描述

2、分析现象本质:
1)it_proc:
内部循环过多:按照it内部的参数默认值计算,最大循环次数达到百万级别,在其他特征收集基本0ms的情况下,it的耗时是不可接受的。
2)信息流配图:
分阶段、逐步细化各步骤的处理时间并不能发现问题原因,这种情况就不能怀疑单次执行内部函数的耗时上,很有可能是系统在做切换、同步等处理时导致的异常。
对这一部分程序重新研读,发现调用的std标准函数random_shuffle有重大嫌疑,在此怀疑的基础上,注释掉相关代码,确实不再发生同样的问题,问题得到确认。

问题参考资料:
http://www.cplusplus.com/refe...
is-random-shuffle-threadsafe-and-using-rand-r-if-it-is-not
https://github.com/mariusmuja...

3、问题修复方式:
1)it_proc:
和策略同学讨论修复方式,谁开发谁维护的原则,发现是按权重抽样算法过于复杂,最后确定已现有ot的处理方式进行修改;
2)信息流配图:
a. 信息流配图也存在大量循环,首先将不需要再循环内部执行的代码移到循环体外部,其次尽量在不影响功能的情况下降低循环次数。
b.对于random_shuffle的问题,采用基于rand_r自定义随机生成器的方式调用
template void random_shuffle (RandomAccessIterator first, RandomAccessIterator last,RandomNumberGenerator&& gen);
实现数组打散。

4、总结:
1)性能问题排查的思路和步骤(定位问题比解决问题更加困难,无法定位问题就更谈不上解决问题)
2)代码优化的原则:
a.阿姆达尔定律:不经常使用的代码不需要做较多优化考虑,即让经常执行的路径运行更加高效,而运行稀少的路径正确执行。
b.先保证代码的正确性,再考虑优化。
c.优化所需的时间常常是写代码时间的double。
3)优化分为系统级别的优化和代码级别的优化
系统级别的优化常常需要模块或子模块的重构,需要从顶端开始出方案和设计。推荐书目:《重构-改善既有代码的设计》
代码级别的优化更多的是使用一下小技巧实现,如果可以参考这几个链接:

http://www.jb51.net/article/5...
http://blog.csdn.net/wind19/a...

图片描述

阅读 705

推荐阅读
聊聊架构
用户专栏

原创、收集、整理互联网架构技术文章

5 人关注
19 篇文章
专栏主页