【发布时间】:2013-10-19 19:16:43
【问题描述】:
我正在尝试使用 python 的 dis 库来试验和了解性能。下面是我尝试的一个实验,有了结果。
import dis
def myfunc1(dictionary):
t = tuple(dictionary.items())
return t
def myfunc2(dictionary, func=tuple):
t = func(dictionary.items())
return t
>>> dis.dis(myfunc1)
4 0 LOAD_GLOBAL 0 (tuple)
3 LOAD_FAST 0 (dictionary)
6 LOAD_ATTR 1 (items)
9 CALL_FUNCTION 0
12 CALL_FUNCTION 1
15 STORE_FAST 1 (t)
5 18 LOAD_FAST 1 (t)
21 RETURN_VALUE
>>> dis.dis(myfunc2)
4 0 LOAD_FAST 1 (func)
3 LOAD_FAST 0 (dictionary)
6 LOAD_ATTR 0 (items)
9 CALL_FUNCTION 0
12 CALL_FUNCTION 1
15 STORE_FAST 2 (t)
5 18 LOAD_FAST 2 (t)
21 RETURN_VALUE
现在,我明白了……
- 最左边的
4和5是行号 - 中间一列是机器调用的操作码
- 右边的列是对象(opargs?)
...但这一切在性能方面意味着什么?如果我试图决定使用哪个函数,我将如何使用dis 来比较两者?
提前致谢。
【问题讨论】:
-
不要为此使用
dis.dis。使用timeit。dis可用于比较不同代码示例之间的字节码差异,这可能会让您了解一个编程构造是否编译为比另一个复杂得多的字节码。对于真正的性能问题,您应该分析、测量执行时间。 -
一般你不能。字节码的执行时间可能大不相同。例如,对 C 函数的调用是单个字节码,但可能需要数年才能执行,而在其他情况下,您有数十个字节码,但都需要几纳秒。要比较性能,请使用分析器。
-
谢谢你们。我什至不知道现在是否需要“答案”。 :-)
-
在这种特定情况下,由于在两个实例中被调用的东西是相同的(因此
CALL_FUNCTION时间无关紧要),我们可以说第二个函数执行得更快。字节码之间的唯一区别是myfunc2使用LOAD_FAST,而1使用LOAD_GLOBAL,因为正在加载的东西是2中的函数参数。由于LOAD_FAST非常快,因为它只加载函数对象的一个槽,而LOAD_GLOBAL使用相当复杂的查找,2将(非常稍微)更快。这也可以通过将func设为局部变量而不是参数来完成。 -
@l4mpi 我认为您的分析是 OP 正在寻找的答案。目前唯一可用的答案告诉 OP 不要使用
dis进行性能分析,这对初学者来说是一个很好的一般建议,但不是这个问题的好答案。您可能想重新发布您的评论作为答案。
标签: python performance python-2.7