最近我们团队把线上的PHP版本从PHP 7.0升级到了PHP 7.2并且开始测试刚发布不久的PHP 7.3在这个过程中做了大量的性能优化工作把一个原本响应很慢的接口从平均800ms优化到了平均120ms提升了将近7倍效果非常明显。
今天想分享一下这次PHP 7.2/7.3性能优化的实战经验包括遇到的问题优化的思路具体的优化手段以及,最终的效果希望能给做PHP开发的朋友一些参考和启发。
一、背景和问题
先说说背景和遇到的问题我们的项目是一个电商平台用PHP开发之前,一直跑在PHP 7.0上运行了两年多一直比较稳定,但是随着业务的发展用户量和数据量都增长了很多系统的响应速度开始变慢特别是几个核心接口,比如商品详情页订单列表等等响应时间越来越长用户反馈页面加载慢体验不好。
其中最严重的是商品详情页接口平均响应时间达到了800ms峰值甚至能到2秒以上严重影响用户体验也影响了转化率我们之前,也做过一些优化,比如加缓存优化SQL等等,但是效果有限响应时间还是在500ms以上达不到预期,所以这次决定下大力气做一次全面的性能优化,并且借这个机会把PHP版本升级到PHP 7.2甚至测试PHP 7.3看看新版本的性能提升效果。
PHP 7.3是2018年12月6日刚发布的稳定版我们也很关注它的新特性和性能提升,所以在升级到PHP 7.2之后,也在测试环境测试了PHP 7.3看看性能表现如何为后续升级做准备。
二、优化思路
做性能优化首先,要有清晰的思路不能盲目优化我们这次的优化思路是先测量再分析,然后针对性优化最后验证效果具体来说,分为以下几个步骤。
第一步:建立性能基准找到瓶颈:
首先,我们用性能分析工具(Xdebug + KCacheGrind以及Blackfire)对慢接口做了详细的性能分析找到到底是哪里慢是SQL查询慢还是PHP代码执行慢还是外部调用慢等等,只有找到真正的瓶颈才能针对性优化,否则就是瞎优化白费力气。
分析结果显示这个接口的时间主要消耗在几个地方:
- 数据库查询:占了大约50%的时候,间有很多慢SQL和重复查询。
- PHP代码执行:占了大约30%的时候,间有一些低效的代码和重复计算。
- 外部调用:占了大约15%的时间调用了一些第三方接口和,内部服务响应比较慢。
- 其他:占了大约5%的时间。
找到了瓶颈之后,我们就可以针对性地逐个优化了。
第二步:从大到小逐个优化:
优化的顺序是从占比最大的瓶颈开始逐个优化,因为占比大的瓶颈优化之后,收益最大能快速看到效果我们先优化数据库查询,然后优化PHP代码,然后优化外部调用最后做一些细节优化和版本升级带来的性能提升。
第三步:每次优化后验证效果:
每次做一个优化之后,我们都会重新做性能测试验证优化效果看看响应时间降了多少有没有引入新的问题这样能确保每个优化都是有效的也能及时发现问题避免优化了半天结果没效果,或者引入了bug。
三、具体优化手段
下面详细说说我们做的具体优化手段以及每个优化的效果。
优化1:数据库查询优化:
数据库查询是最大的瓶颈占了50%的时间,所以我们首先,从这里入手做了以下几个优化。
1.1 慢SQL优化:
首先,我们把接口里的所有SQL都列了出来用EXPLAIN分析每个SQL的执行计划找到慢SQL然后针对性优化发现有几个SQL没有走索引全表扫描导致很慢我们给这些SQL涉及的字段加了合适的索引之后,这些SQL的执行时间从几百ms降到了几ms提升非常明显。
另外,还有一些SQL写得比较低效,比如用了SELECT *查询了不需要的字段,或者用了子查询而不是JOIN或者用了OR条件导致索引失效等等我们把这些SQL都改写了优化了写法性能也有不少提升。
1.2 减少重复查询(N+1问题):
然后我们发现接口里有比较严重的N+1查询问题,比如查询商品列表之后,循环每个商品再查询商品的分类信息库存信息等等导致执行了很多条SQL我们把这些循环里的查询改成了批量查询用IN条件一次查询出所有数据,然后在PHP里组装这样SQL的数量从几十条降到了几条大大减少了数据库交互的开销性能提升很明显。
N+1问题是PHP开发中非常常见的性能问题特别是用了ORM的项目很容易不知不觉就产生N+1查询,所以一定要注意检查SQL的数量避免循环里执行SQL。
1.3 加缓存:
然后我们给一些不经常变化的数据加了缓存,比如商品分类信息品牌信息配置信息等等这些数据变化频率很低,但是每次请求都要查询数据库我们把这些数据缓存到Redis里设置合适的过期时间,并且在数据更新的时候,主动删除缓存这样大部分请求都直接从缓存读取不用查数据库大大减轻了数据库压力也提升了响应速度。
另外我们还给整个商品详情页接口加了页面缓存,因为商品详情的信息变化不是特别频繁我们把接口的返回结果缓存到Redis里设置5分钟的过期时间商品信息更新的时候,主动删除缓存这样大部分请求直接返回缓存结果不用执行任何逻辑和查询响应时间直接降到了10ms以内效果非常好,当然页面缓存要注意缓存失效的问题以及个性化信息(比如用户登录状态购物车数量等等)的处理我们是把个性化信息通过前端AJAX单独加载页面主体内容用缓存这样既保证了性能又不会出现个性化信息错乱的问题。
优化2:PHP代码优化:
数据库优化完之后PHP代码执行的占比就凸显出来了我们,接着做了PHP代码的优化。
2.1 减少重复计算和冗余代码:
首先,我们发现代码里有一些重复计算和冗余代码,比如同一个数据在不同的地方重复查询和计算,或者一些已经不需要的旧代码还在执行我们把这些都清理了把重复的计算结果存起来复用删除了不需要的冗余代码这样减少了不必要的计算开销性能有一定提升。
2.2 优化字符串处理和数组操作:
然后我们发现代码里有一些低效的字符串处理和数组操作,比如在循环里反复拼接字符串(用.运算符)或者用inarray在大数组里查找而不是用isset查哈希表等等我们把这些都优化了字符串拼接改成先放数组里最后用implode拼接数组查找改成用arrayflip转成哈希表,然后用isset查找等等这些优化,虽然单个看提升不大,但是积少成多整体也有不少提升。
2.3 利用PHP 7.2/7.3的新特性:
另外我们也利用了PHP 7.2和PHP 7.3的一些新特性来优化代码,比如PHP 7.2的object类型参数和返回值类型声明能让代码更规范也能在一定程度,上提升性能,因为类型声明能帮助PHP的OPcache做更好的优化,还有PHP 7.2的password_hash性能提升等等。
PHP 7.3虽然刚发布不久,但是我们在测试环境测试了一下发现PHP 7.3相比PHP 7.2在很多场景下都有性能提升特别是字符串处理和数组操作的性能提升比较明显,还有PHP 7.3的JSON解析性能也提升了不少我们的接口有大量的JSON处理,所以升级到PHP 7.3之后,性能,还有进一步的提升,当然PHP 7.3刚发布我们还在测试验证稳定性暂时没有上生产,但是测试环境的性能数据很让人期待。
2.4 开启OPcache并优化配置:
还有一个很重要的优化就是开启OPcache并且优化配置OPcache是PHP内置的字节码缓存能把PHP脚本编译后的字节码缓存起来避免每次请求都重新编译能大大提升PHP的性能我们之前,虽然开启了OPcache但是配置不是最优我们调整了OPcache的配置,比如增大opcache.memoryconsumptionopcache.internedstringsbufferopcache.maxacceleratedfiles等等让更多的脚本能被缓存,并且开启opcache.validatetimestamps但是设置合适的opcache.revalidate_freq减少文件检查的开销调整之后PHP的执行性能又有不少提升。
另外我们还开启了opcache.enablefileoverride和opcache.fast_shutdown等配置进一步提升性能OPcache的优化,虽然简单,但是效果非常明显很多PHP项目性能不好就是,因为OPcache没配置好,所以一定要重视OPcache的配置。
优化3:外部调用优化:
然后我们优化了外部调用的性能接口里调用了一些第三方接口和,内部服务这些调用的响应时间比较长占了15%的时间。
3.1 并行调用:
首先,我们发现有几个外部调用是串行执行的,但是它们之间,没有依赖关系可以并行执行我们把这些调用改成了并行调用用curl_multi或者Guzzle的异步请求来并行执行这样几个调用的总时间从几个调用时间之和变成了最慢那个调用的时间大大减少了等待时间性能提升很明显。
3.2 加缓存和降级:
然后我们给一些外部调用的结果加了缓存,因为这些接口返回的数据变化不是很频繁,比如物流信息支付配置等等我们把调用结果缓存起来设置合适的过期时间这样大部分请求不用真正调用外部接口直接从缓存读取大大提升了速度也减少了对外部接口的依赖。
另外我们还加了降级机制当外部接口调用失败,或者超时的时候,用缓存的数据,或者默认值兜底保证接口不会,因为外部接口的问题而整体不可用提升了系统的稳定性和可用性。
3.3 超时设置:
还有我们给所有外部调用都设置了合理的超时时间之前,有些调用没有设置超时,或者超时设置得太长导致外部接口慢的时候,我们的接口也跟着慢甚至卡住设置合理的超时之后,外部接口慢的时候,能快速失败,然后走降级逻辑不会拖慢整个接口这也很重要。
优化4:其他细节优化:
除了上面的主要优化我们还做了一些细节优化,虽然单个提升不大,但是积少成多整体也有不少帮助。
比如优化了session的存储把默认的文件存储改成了Redis存储减少了文件IO的开销也提升了并发能力再,比如优化了autoload用composer的类映射优化减少了类加载的开销,还有优化了日志记录避免在循环里写日志,或者记录过多的调试日志减少了IO开销等等。
四、PHP版本升级的性能提升
这次优化的,同时我们也把PHP版本从7.0升级到了7.2并且测试了7.3版本升级本身也带来了不少性能提升。
PHP 7.0 → 7.2的提升:
从PHP 7.0升级到PHP 7.2我们做了性能对比测试在相同的代码和环境下PHP 7.2比PHP 7.0整体性能提升了大约15%-20%主要提升在几个方面:
- 字符串处理性能提升:PHP 7.2优化了很多字符串函数的性能。
- 数组操作性能提升:数组的遍历查找等操作性能有提升。
- 对象和类型声明优化:PHP 7.2对对象和,类型声明做了优化执行更高效。
- 内存使用优化:PHP 7.2的内存使用更高效同样的请求内存占用更少。
而且PHP 7.2还移除了一些过时的扩展和功能让内核更精简也有助于性能提升升级到PHP 7.2之后,我们的接口响应时间整体又降了一些效果不错。
PHP 7.3的测试表现:
PHP 7.3是2018年12月6日刚发布的稳定版我们在测试环境做了性能测试发现PHP 7.3相比PHP 7.2又有大约10%-15%的性能提升特别是在我们的场景下,因为有大量的JSON处理和字符串处理PHP 7.3对这些都做了优化,所以提升比较明显。
PHP 7.3的一些主要性能提升包括:
- JSON解析性能提升:
jsondecode和,jsonencode的性能有明显提升。 - 字符串处理优化:很多字符串函数性能提升。
- 灵活的Heredoc和Nowdoc语法:虽然主要是语法改进,但是也间接提升了代码的可维护性。
- GC和内存管理优化:PHP 7.3对垃圾回收和,内存管理做了优化内存使用更高效。
不过PHP 7.3刚发布我们还在测试验证兼容性和稳定性特别是一些第三方扩展是否支持PHP 7.3所以暂时没有上生产,但是测试环境的性能数据很让人期待等验证稳定之后,会考虑升级到PHP 7.3。
五、最终效果
经过上面的一系列优化我们的商品详情页接口性能有了巨大的提升从优化前的平均800ms降到了优化后的平均120ms提升了将近7倍峰值响应时间也从2秒以上降到了300ms以内效果非常明显。
具体的性能数据对,比如下:
- 优化前:平均响应时间 800msP95 1500msP99 2200ms
- 优化后(PHP 7.2):平均响应时间 120msP95 250msP99 350ms
- 测试环境PHP 7.3:平均响应时间 100msP95 200msP99 280ms
可以看到优化效果非常显著用户体验大大提升页面加载速度快了很多用户反馈也很好转化率也有一定提升,而且服务器的CPU和内存使用率也降了不少原来高峰期CPU使用率能到80%现在,只有30%左右大大减轻了服务器压力也节省了成本。
六、经验和总结
这次PHP性能优化的实战让我学到了很多这里总结一些经验和心得分享给大家。
经验1:性能优化要先测量不要瞎优化:
这是最重要的经验做性能优化一定要先测量找到真正的瓶颈,然后针对性优化不要凭感觉瞎优化很多人做性能优化喜欢一上来就改代码优化这个优化那个,但是可能优化的地方根本不是瓶颈白费力气还可能引入bug所以一定要先用性能分析工具找到瓶颈,然后从占比最大的瓶颈开始优化这样才能事半功倍。
经验2:数据库往往是最大瓶颈要重点优化:
在大部分PHPWeb项目中数据库往往是最大的性能瓶颈,所以做性能优化要重点关注数据库的优化包括慢SQL优化索引优化减少重复查询加缓存等等这些优化往往能带来最大的性能提升我们这次优化一半以上的性能提升都来自数据库优化,所以一定要重视数据库的优化。
经验3:缓存是性能优化的利器:
缓存是性能优化的利器合理使用缓存能大大提升性能减轻后端压力我们这次用了多级缓存包括数据缓存页面缓存等等效果非常好,当然缓存也不是银弹要注意缓存一致性的问题以及缓存穿透击穿雪崩等问题要合理设计缓存策略才能既提升性能又保证数据一致性。
经验4:PHP版本升级能带来不小的性能提升:
很多PHP项目还在用比较旧的PHP版本,比如PHP 5.6甚至PHP 5.3其实升级到PHP 7.x能带来非常大的性能提升PHP 7比PHP 5.6性能提升了一倍以上PHP 7.27.3又在PHP 7的基础上有进一步提升,所以,如果你的项目还在用旧版本的PHP强烈建议升级到最新的稳定版性能提升会让你惊喜,当然升级之前,要做好兼容性测试确保代码和扩展都能兼容新版本。
经验5:OPcache配置很重要不要忽视:
OPcache是PHP性能优化中最简单也最有效的手段之一,但是很多人忽视了OPcache的配置只是简单开启就完事了其实合理配置OPcache能带来很大的性能提升,所以一定要根据自己的项目情况优化OPcache的配置,比如内存大小缓存文件数等等让OPcache发挥最大的作用。
七、写在最后
以上就是这次PHP 7.2/7.3性能优化实战的全部内容包括背景问题优化思路具体优化手段PHP版本升级的性能提升最终效果以及,经验总结希望能给做PHP开发的朋友一些参考和启发。
性能优化是一个持续的过程不是一次优化就一劳永逸的随着业务的发展数据量的增长新的性能问题会不断出现,所以要建立性能监控和持续优化的机制定期检查系统性能及时发现和解决性能问题这样才能保证系统长期稳定高效运行。
PHP虽然经常被黑性能不好,但是实际上,现代的PHP 7.x性能已经非常好了配合合理的优化完全能支撑大流量的网站和应用关键是要会用会优化希望大家都能用好PHP写出高性能的应用。
最后用一句话结束这篇文章:"性能优化没有捷径先测量再优化从瓶颈入手持续迭代就能从慢到快让系统飞起来。"
愿大家的PHP项目都能跑得又快又稳用户体验棒棒的。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录