高性能编码重要性

 背景:一客户反馈产品在使用过程中经常出现卡死、响应时间慢,CPU经常爆满。

        经现场初步分析:发现在% Time in GC 占用高达90%,而一般情况下也就一两个百分点。由于GC一直在回收垃圾,所以客户端与服务端连接响应时间长,传输数据慢。

        获取dump文件分析线程有好几个线程都在做GC回收工作,其中发现有一个线程执行String.Concat执行了35S,而且还在执行中。所以进一步分析为String.Concat滥用,不断创建新的Sring,导致GC一直在回收。我们继续研究了下这个线程执行的方法参数,看到两个参数,参数1太大,看不全,参数2是一个类似GUID的值,然后更进一步确认进行的应该是字符串连接操作。类似于下面这样:        

如果a的值比较大,那么再加b的话就会慢,gc回收也会比较慢。代码反编译后看到这样的代码:

        

        这里产生了成千上万个近8M大小的字符串不断更新,根据线程看出产生了(7887918byte/92=产生了85738个对象)foreach循环了这么多次,所以GC一直在忙于回收新产生的String对象,消耗了大量的资源。

        解决方案:用StringBuilder(StringBuffer)代替String.Concat (“+”),调用StringBuilder的Append方法时StringBuilder对象不会复制新的对象,而是生成新的StringBuilder对象,并用里面的orinal指向原来的对象。相当于引用指向所有零散自渡船的地址。StringBuilder类型的对象集合在内存中存储可能不是连续的,是一个链表结构;而String.Concat则不一样,a=a+b 中的=运算符每运算一次总是生成新的对象;另外=运算符也比较耗时,不如StringBuilder.Append效率高。StringBuffer是线程安全的,执行效率比StringBuilder效率低点。

        StringBuilder>StringBuffer>String.Concat。

        高性能编码非常重要,平常编码看不出什么差别,但是真正运行时却是天壤之别。
https://mp.weixin.qq.com/s/KFCw6JH2GO9kPMEGnmPgDg

猜你喜欢

转载自blog.csdn.net/zhuaizhuaihenguai/article/details/80006865