Python性能分析实战1
前置知识
- Python 基础语法
- cProfile 基本使用
问题
环境上发现有接口请求的响应时间高达10s以上,严重影响功能的使用
需要分析具体的代码执行耗时,针对问题代码进行优化,优化接口性能
解决思路
分析代码执行情况
使用 cProfile 工具,将目标接口的代码执行情况dump
到文件中
1 |
|
获得dump
文件后,使用 snakeviz 渲染方便查看
1 |
|
执行命令后,snakeviz 会自动打开浏览器显示渲染后的结果
可以看到接口中调用的service
方法耗时长达10s左右,根据图示的调用栈可以看到耗时久主要是跟一个decrypt
方法有关
接下来到底下的搜索框过滤出关于decrypt
相关的执行情况
可以看到,decrypt
相关的方法被调用37次,每次耗时0.2s
左右
0.2s
算是比较耗时的操作了,这样耗时的代码逻辑居然还执行了37次,最终导致总耗时有7s
之多
分析问题代码
找到了可能有问题的代码位置,接下来就要看看对应的代码逻辑了
本文中代码涉及私密信息,仅以伪代码的方式进行讲解
decrypt
实际上是一个解密的方法,解密算法需要进行大量的运算,这也解释了为什么这个操作单次就需要耗费0.2s
了
为什么需要这个解密操作
这里实际上是对需要连接的中间件密码进行解密
伪代码如下:
1 |
|
生产环境中的密码都是经过加密处理的,所以这里需要解密的操作
那么就是说这个操作不可避免,也没有很大优化空间了
这里就有个疑问了,既然只是一个密码解密的操作,且只是一个配置类,为什么需要调用那么多次,只需要在服务启动之时进行一次初始化的操作就可以了
尝试修复
根据查看代码逻辑后分析的原因,尝试将解密的操作放到初始化的流程中,并使用functools.cached_property
缓存计算结果(这样就可以保证只进行一次计算,后续直接从缓存获取结果)
伪代码如下:
1 |
|
还没结束?
代码修改后再次dump
查看优化结果
看起来优化的效果还是很明显的,但是接口仍然有2s
的耗时,没有达到预期的效果
分析耗时主要是在service
中一个查询instance
的方法,通过id
查询 Mongo
这里查询数据的操作就耗费了2s
这里按道理如果这是个单独的一次查询,2s
已经属于慢查询了,但是并没有接到慢查询的告警消息
可以先猜测下原因