简介: 性能优化不言而喻的益处是可能节约机器资源。如果一个有2000台服务器的利用,整体性能晋升了10%,实践上来说,就相当于节俭了200台的机器。除了节俭机器资源外,性能好的利用绝对于性能差的利用,在应答流量突增时更不容易达到机器的性能瓶颈,在同样流量场景下进行机器扩容时,也只须要更少的机器,从而可能更快的实现扩容、应急操作。所以,性能好的利用绝对于性能差的利用在稳定性方面也更胜一筹。
作者 | 金盛杰(司旭)起源 | 阿里开发者公众号一、背景1.1 业务背景支付宝卡包寄存着用户的会员卡和优惠券。无论是卡券cell,还是卡券详情,都是通过动态模板配置加上动静可变数据,最终出现给终端用户的。上面【图1】展示了卡券数据在C端用户的展示模式,【图2】示意了C端数据组装过程。
【图1】卡券数据在C端展示模式
【图2】C端数据组装过程 以【图2】为例,模板中有availableAmount 和voucherName 两个变量,这两个变量在动静变量数据有对应的值。用动静的值替换掉模板外面对应的这两个变量,最初拼装成“100元红包名称”。当这个红包被应用了一次,生产了30元后,动态数据外面availableAmount 的值就会变成70。用户再次进入到红包详情页时,展示数据从新组装后就会变成“70元红包名称”。1.2 问题发现最近做我的项目过程中,把卡券组装渲染逻辑好好的梳理了一遍,其中认真研读了【图3】这段模板变量替换逻辑。这是一段老代码,从卡包产品诞生之日起就存在,差不多有十年的工夫了。其作用就是用动态数据替换掉模板外面的变量。这段代码逻辑咋一看,并没有什么问题,就是把模板外面两个$ 之间(蕴含)的变量,用动态数据进行替换。思考到这是一段极为外围又高频的调用逻辑,于是看看有没有性能优化的空间。
【图3】模板变量替换代码实现 把替换逻辑厘清了之后,第一感觉就是这段代码有性能晋升的空间。次要有两点:1、每次while 循环进行了两次indexOf 操作2、每次while 循环都进行了substring 操作于是,就有了上面两个疑难:1、可能缩小indexOf 和substring 操作吗?2、真的每次都要进行模板变量查找吗?二、性能优化带着下面两个问题,逐渐进行性能优化并测试。整个优化过程一共迭代了5版,并最终获得了性能晋升超过10倍的成果。上面别离来介绍下不同版本的实现和性能比照。2.1 性能优化V1这一版去掉了indexOf 和substring 操作,转而应用另一种替换形式。之前的替换逻辑是从头到尾循环模板内容字符串,遇到$ 之间的变量就进行替换,过程中须要一直的进行indexOf 和substring 操作。新的实现形式是在进行变量替换之前,通过循环模板内容字符串,利用双指针把模板外面所有变量都提取进去,再对变量汇合进行循环,顺次替换掉模板内容外面的变量。
【图4】性能优化V1代码实现 2.2 性能优化V2动态模板配置个别状况下不会产生变更。也就意味着,同一个模板对应的变量都是固定不变的。能够将模板id和模板变量汇合进行一对一的缓存,缩小每次替换之前的变量提取。在决定应用缓存之前,要想好怎么实现缓存。有两点须要留神:1、用本地缓存代替TBase,缩小大流量场景下对TBase的压力2、怎么管制本地缓存的无效数量,并在无限的内存占用状况下最大化缓存效率能够借助Google Guava库的缓存类来实现缓存逻辑,示例代码见【图5】
【图5】缓存实现示例代码
【图6】性能优化V2代码实现 2.3 性能比照 (1)做完下面两步之后进行了性能测试,性能对比方【图7】所示。
【图7】V1、V2版性能比照 通过性能比照发现,V1版绝对于原始版有性能晋升,带缓存的V2版绝对于不带缓存的V1版也有性能晋升。但随着流量增大,性能优化成果逐渐削弱。阐明V1、V2版耗时优化的点,在整个模板变量替换耗时中占比并不高。也同时阐明,整个模板变量替换逻辑当中,还存在其余更为耗时的点。回过头来再认真看一遍变量替换逻辑,忽然间意识到脱漏了一个”大问题“。就是这个String.replace 办法,该办法有两个耗时点:1、每次replace 都会进行模板编译2、replace 都是创立一个新的对象进行返回并且每次replace 之后还要进行变量的从新赋值。
【图8】String.replace 代码实现 2.4 性能优化V3在V2版根底上,去掉replace 办法,用StringBuilder 来实现。
【图9】性能优化V3代码实现 StringBuilder 实现过程中有一点要留神。V2版本中,提取变量返回的是一个Set 汇合。返回汇合中呈现变量的程序和模板中变量程序会不统一,模板中有多个雷同变量的状况下,也只会替换第一个呈现的变量。所以要将变量提取返回的后果换成有序可反复的List ,能力保障逻辑的正确性。2.5 性能优化V4V3版优化之后,性能晋升显著,证实String.replace 办法才是整个模板变量替换逻辑中最为耗时的点。于是在原办法上只用StringBuilder 来替换String.replace ,失去V4版。
【图10】性能优化V4代码实现 2.6 性能比照(2)
【图11】V1、V2、V3、V4版性能比照 通过【图11】能够显著的发现,在进行StringBuilder 实现后,性能晋升超过10倍,成果非常显著。V4版耗时实际上比V3版带缓存的还要少,阐明V3版先提取变量再进行StringBuilder 组装的过程,相对来说还是会更耗时一点。但V4版的代码可读性是不如V3版的,能够把V3版和V4版相结合,剔除掉缓存依赖,产生一个代码可读性和性能最佳的V5版。2.7 性能优化V5先提取变量,去掉缓存依赖,用StringBuilder 替换掉String.replace ,减少代码可读性。
【图12】V5版代码实现&100万次循环耗时比照 三、总结通过下面5个版本的性能优化,性能失去了超过10倍的晋升。性能由高到低的程序是V4 > V3 > V5 > V2 > V1 > 未被优化的原始版。其中V3、V4、V5版的性能显著优于V1和V2版,证实这段模板替换逻辑最为耗时的点为String.replace ,V3 > V5和V2 > V1表明,引入缓存对性能晋升还是有肯定帮忙的。在代码可读性方面,V4是不如V3和V5的。整个优化总结下来次要有两点:1、String.replace 办法波及到模板编译和新字符串生成,比拟吃资源2、StringBuilder 代替String.replace ,除了可能缩短调用耗时,在空间上也可能缩小资源占用。因为StringBuilder.append 绝对于String.replace 来说,可能缩小两头大量String 对象的创立和销毁,可能缩小GC的压力,从而升高CPU的负载。性能优化不言而喻的益处是可能节约机器资源。如果一个有2000台服务器的利用,整体性能晋升了10%,实践上来说,就相当于节俭了200台的机器。除了节俭机器资源外,性能好的利用绝对于性能差的利用,在应答流量突增时更不容易达到机器的性能瓶颈,在同样流量场景下进行机器扩容时,也只须要更少的机器,从而可能更快的实现扩容、应急操作。所以,性能好的利用绝对于性能差的利用在稳定性方面也更胜一筹。最初再回到本次文章的主题:是什么让一段20行代码的性能晋升了10倍?我的答复是:StringBuilder yyds!举荐浏览1.代码圈复杂度治理小结2.如何写出无效的单元测试3. java利用提速(速度与激情) 《低代码引擎技术白皮书》 低代码引擎是一款为低代码平台开发者提供的,具备弱小定制扩大能力的低代码设计器研发框架。本书从利用、根底协定和原理三个方面对低代码引擎的技术进行了全面的介绍,并在低代码引擎原理篇重点介绍了低代码引擎所需的渲染、入料、编排、出码等核心技术原理,对低代码引擎的生态设计进行了介绍。本书适宜于有低代码产品研发诉求的前端开发人员。点击这里,查看详情。原文链接:https://click.aliyun.com/m/10...本文为阿里云原创内容,未经容许不得转载。