Python代码在执行的时候,会被编译为Python字节码,再由Python虚拟机执行Python字节码。有时候就我们执行python文件的时候会生成一个pyc文件,这个pyc文件即用于存储Python字节码指令,而这些字节码是一种类似于汇编指令的中间语言,但是每个字节码对应的不是机器指令,而是一段C代码。


而Dis模块,就是用于查看这些字节码的运行轨迹,因此我们可以用Dis模块判断两个函数的内存占用谁会更大,谁会更消耗CPU性能,不仅如此,通过指令,我们还可以知道Python中一些内置函数、变量的取值过程、运行逻辑,对于我们优化代码很有帮助。


下面将通过两个例子,来介绍Dis模块的使用。


1.为什么下面第一个函数比第二个函数耗得内存更少?

python 代码深层次性能分析 — Dis模块_python

python 代码深层次性能分析 — Dis模块_python_02


一般人是比较难直接看出来的,但是我们使用Dis模块却能很容易找到答案:


python 代码深层次性能分析 — Dis模块_字节码_03


结果:


python 代码深层次性能分析 — Dis模块_字节码_04


Dis的结果其实很容易阅读:


第一列:对应的源代码行数。
第二列:​对应的内存字节码的索引位置。
在第一列和第二列之间的 >> 号表示跳转的目标
第三列:​内部机器代码的操作。
第四列:​指令参数。
第五列:​实际参数。


两个函数的dis分析用*号隔开了,大家可以清晰地看到两个函数之间的语句区别。第二个函数的字节码索引最大到了30,而第一个函数的字节码索引最大仅到了22,因此,第一个函数耗得内存比第二个函数少。


而且,在第一列和第二列之间的 >> 号表示跳转的目标,大家可以看第二个函数第四列的 18,表示其跳转到了索引为18的指令,也就是ROT_TWO。第二个函数的跳转也比第一个函数多,这也可能导致其在某种特殊情况下的效率可能会比第一个函数低。


2.为什么Python2中,while True 比 while 1慢?

while 1:
pass
while True:
pass

可以通过在命令中使用dis进行分析:


python 代码深层次性能分析 — Dis模块_汇编指令_05


以看到,while 1 在第二行是直接JUMP_ABSOLUTE,因此相比于While True 少了LOAD_NAME 和 POP_JUMP_IF_FALSE。这是因为True在Python2中不是一个关键字,而是一个内置变量,因此每次Python都会用LOAD_NAME去检查(POP_JUMP_IF_FALSE)True的值。这就是为什么While True 比while 1慢的原因。


到了Python3,True变成了关键字,就没有这个问题了:


python 代码深层次性能分析 — Dis模块_字节码_06


Python 3 针对 Python 2 做了非常多的替换,这也是为什么它不兼容 Python 2 的原因之一,差别太大了。因此,建议各位初学者直接上手 Python 3 进行学习,而非 Python 2.


希望​以上两个Dis模块的使用例子能给大家带来一点灵感,分析一段Python代码的深层次性能问题虽然比较费时费力,但是一旦你分析到了深层次的性能原因,将能累积不少深层次的技术上的知识,写出更漂亮的代码。


如果你喜欢我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞python 代码深层次性能分析 — Dis模块_python_07,有任何问题都可以在下方留言区留言,我们都会耐心解答的!

Python实用宝典 (pythondict.com)

不只是一个宝典

欢迎关注公众号:Python实用宝典python 代码深层次性能分析 — Dis模块_python_08