python - 为什么 python 中的空函数调用对于动态编译的 python 代码要慢 15% 左右

标签 python optimization dynamic python-2.7 micro-optimization

这是非常糟糕的微优化,但我只是好奇。它通常不会在“真实”世界中产生影响。

所以我正在使用 compile() 编译一个函数(什么都不做),然后对该代码调用 exec 并获取对我编译的函数的引用。然后我执行它几百万次并计时。然后用局部函数重复它。为什么动态编译的函数仅调用就慢了大约 15%(在 python 2.7.2 上)?

import datetime
def getCompiledFunc():
  cc = compile("def aa():pass", '<string>', 'exec')
  dd = {}
  exec cc in dd
  return dd.get('aa')

compiledFunc = getCompiledFunc()  
def localFunc():pass


def testCall(f):
  st = datetime.datetime.now()
  for x in xrange(10000000): f()
  et = datetime.datetime.now()
  return (et-st).total_seconds()

for x in xrange(10):
  lt = testCall(localFunc)
  ct = testCall(compiledFunc)
  print "%s %s %s%% slower" % (lt, ct, int(100.0*(ct-lt)/lt))

我得到的输出是这样的:

1.139 1.319 15% slower

最佳答案

dis.dis() 函数显示每个版本的代码对象是相同的:

aa
  1           0 LOAD_CONST               0 (None)
              3 RETURN_VALUE        
localFunc
 10           0 LOAD_CONST               0 (None)
              3 RETURN_VALUE 

所以区别在于函数对象。我比较了每个字段(func_doc、func_closure 等),不同的是 func_globals。换句话说,localFunc.func_globals != compiledFunc.func_globals

提供你自己的字典而不是内置的全局变量是有代价的(前者必须在每次调用时创建堆栈帧时查找,而后者可以由已经知道的 C 代码直接引用关于默认的内置全局字典)。

这很容易验证,只需将代码中的 exec 行更改为:

exec cc in globals(), dd

随着那个的改变,时间差异消失了。

谜底揭晓!

关于python - 为什么 python 中的空函数调用对于动态编译的 python 代码要慢 15% 左右,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8191390/

相关文章:

java - Android:将选择的不同布局动态加载到另一个布局中

C# 动态无法从基接口(interface)调用方法

python - pd.read_csv 添加名为“Unnamed : 0 的列

python - 学习影响给定列表值的两个数据帧之间关系的最佳方法是什么?

c++ - 这些 C++ 代码是否针对添加 2 个正大整数进行了优化?

java - 伽罗瓦域 GF(4) 中乘法的恒定时间

java - 在java中调用random类的random方法

python - Tensorflow GAN 没有为任何变量提供梯度

python - TypeError : QTreeWidget. setModel() is a private method 的解决方案是什么

iphone - iPhone 上的编译器优化和 UIView 框架