快捷导航

聊一聊:提升18倍的性能优化

[复制链接]
查看: 0|回复: 0
发表于 2 小时前 | 显示全部楼层 |阅读模式

背景比较近负责的一个自研的D注册中心经常收到CPU使用率的告警,于是进行了一波优化,效果还不错,于是打算分享下思考、优化过程,希望对大家有一些帮助。自研D注册中心是个什么东西,我画个简图大家稍微感受一下就好,看不懂也没关系,不影响后续的理解。C和P的服务发现请求(注册、注销、订阅)都发给A,由它全权代理R和A保持G长链接,长链接的目的主要是P方有变更时,能及时推送给相应的C。为了保证数据的正确性,做了推拉结合的机制,A会每隔一段时间去R拉取订阅的服务列表A和业务服务部署在同一台机器上,类似SM的思路,尽量减少对业务的入侵,这样就能快速的迭代了回到今天的重点,这个注册中心比较近CPU使用率长期处于中高水位,偶尔有应用发布,推送量大时,CPU甚至会被打满。以前没感觉到,是因为接入的应用不多,比较近几个月应用越接越多,慢慢就达到了告警阈值。寻找优化点由于这项目是G写的(不懂G的朋友也没关系,本文重点在算法的优化,不在工具的使用上),找到哪里耗CPU还是挺简单的:打开即可,去线上采集一段时间即可。具体怎么操作可以参考我之前的这篇文章,今天文章中用到的知识和工具,这篇文章都能找到。CPU截了部分图,其他的不太重要,可以看到消耗CPU多的是ACP方法,与其直接关联的是2个相关的方法1个叫UW的方法稍微解释下,ACP方法是构造返回D的,由于会在返回时对其做一些处理(比如调整权重等),会涉及到对这个D的解析。又由于推拉结合的模式,线上服务使用方越多,这个处理的QPS就越大,所以它占用了大部分CPU一点也不奇怪。这两个操作可能是序列化占用了CPU,更大头在UW,有点琢磨不透。接下来我们就分析下UW如何优化,因为他占用CPU比较多,优化效果肯定比较好。下面是UW的伪代码:AUW(,W){,:=P()!={},:=PQ(RQ)!={}G(_)!={}W:=100G()!={W,=A(G())!={W=100}}S(,I(W*W))RQ=E()S()}传参是D的,W是机房权重。根据配置的机房权重,将中的进行重新计算,实现多机房流量按权重的分配。这个过程涉及到参数的解析,再进行的计算,比较后再还原为一个D的结构和普通结构一致,其特点是参数可能比较多,没有#后面的片段部分。CPU主要就消耗在这两次解析和比较后的还原中,我们看这两次解析的目的就是为了拿到中的_和参数。P和PQ都是G官方提供的库,各个语言也都有实现,其核心是解析为一个对象,方便地获取的各个部分。如果了解信息熵这个概念,其实你就大概知道这里面一定是可以优化的。S(香农)借鉴了热力学的概念,把信息中排除了冗余后的平均信息量称为信息熵。P和PQ在这个场景下解析肯定存在冗余,冗余意味着CPU在做多余的事情。因为一个D参数通常是很多的,我们只需要拿这两个参数,而P解析了所有的参数。举个例子,给定一个数组,求其中的比较大值,如果先对数组进行排序,再取比较大值显然是存在冗余操作的。排序后的数组不仅能取比较大值,还能取第二大值、第三大值比较小值,信息存在冗余了,所以先排序肯定不是求比较大值的比较优解。优化优化获取参数性能首想法是,不要解析全部,只拿相应的参数,这就很像我们写的算法题,比如获取参数,它只可能是这两种情况(不存在#,所以简单很多)::127001:20880MDS=100:127001:20880MDS==100要么是=,要么是=,结束要么是,要么直接到字符串尾,代码就很好写了,先手写个解析参数的算法:GUQP(,)(,){:=B{}WS()WS(=):=I(,S())(==-1)||(+()+1()){,UPNE}=B{}:=+()+1;();++{+1(){}[:+1]=={}WS([:+1])}S(),}原先获取参数的方法可以摘出来:PBUP(,){,:=P()!={},:=PQ(RQ)!={}G()}先对这两个函数进行:BGQP(*B){:=0;N;++{PBUP(,)PBUP(,)PBUP(,_)}}BGQPN(*B){:=0;N;++{GUQP(,)GUQP(,)GUQP(,_)}}B结果如下:BGQP-41034129708BGQP-41117949685BGQP-41156999818BGQPN-42961254409BGQPN-42944274406BGQPN-42895690405可以看到性能大概提升了20多倍新写的这个方法,有两个小细节,首是返回值中区分了参数是否存在,这个后面会用到;第二是字符串的操作用到了B,这也是实际测试的结果,使用+或者S性能都没这个好,感兴趣可以测试下看看。优化写入参数性能计算出后再把写入中,这里直接给出优化后的代码:AUWN(,W){W==1{}WS,1:=GUQP(,_)1==WS!={}W:=100S,2:=GUQP(,)S!={W,=A(S)!={W=100}}2!={中不存在U:=B{}UWS()C(,){UWS(=)UWS(I(W*W))US()}{UWS(=)UWS(I(W*W))US()}}{中存在WS:=B{}WSWS(=)WSWS(S)WS:=B{}WSWS(=)WSWS(I(W*W))RA(,WSS(),WSS())}}主要就是分为中是否存在两种情况来讨论:本身不存在参数,则直接在后拼接一个参数,当然要注意是否存在本身存在参数,则直接进行字符串替换细心的你肯定又发现了,当W=1时,直接返回,因为W=1时,后面的计算其实都不起作用(D权重默认为100),索性别操作,省点CPU。全部优化完,总体做一下:BAUW(*B){:=0;N;++{_,:=[]{,1,2,3}{AUW(,60)}}}BAUWN(*B){:=0;N;++{_,:=[]{,1,2,3}{AUWN(,60)}}}结果如下:BAUW-43427533289BAUW-43664632432BAUW-43670232740BAUWN-45736841851BAUWN-46469521832BAUWN-45633921896大概提升18倍性能,而且这可能还是比较差的情况,如果传入W=1,效果更好。效果优化完,对改动方法写了相应的单元测试,确认没问题后,上线进行观察,CPUI(空闲率)提升了10%以上比较后其实本文展示的是一个G程序非常常规的性能优化,也是相对来说比较简单,看完后,大家可能还有疑问:为什么要在推送和拉取的时候去解析呢不能事先算好存起来吗为什么只优化了这点,其他的点是否也可以优化呢针对首个问题,其实这是个历史问题,当你接手系统时他就是这样,如果程序出问题,你去改整个机制,可能周期比较长,而且容易出问题第二个问题,其实刚也顺带回答了,这样优化,改动比较小,收益比较大,别的点没这么好改,短期来说,拿收益比较重要。当然我们后续也打算对这个系统进行重构,但重构之前,这样优化,足以解决问题。机房建设的具体问题可以到我们网站了解一下,也有业内领域专业的客服为您解答问题,为成功合作打下一个良好的开端!https://item.taobao.com/item.htm?id=610899018736
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

精彩推荐

让起名更简单

  • 反馈建议:麻烦到管理处反馈
  • 我的电话:这个不能给
  • 工作时间:周一到周五

关于我们

云服务支持

精彩文章,快速检索

关注我们

Copyright 学习建站日志  Powered by©  技术支持:飛    ( 闽ICP备2023005063号 )