“缓存”字符串:为什么没有效果?

时间:2019-10-17 09:42:51

标签: python python-3.x micro-optimization

我尝试了一些测试:

import timeit

a = "hi"

def f():
    return "hi"

def g():
    return a

timeit.timeit("f()", globals={"f": f}, number=100000000)
# 6.028764325194061
timeit.timeit("g()", globals={"g": g, "a": a}, number=100000000)
# 6.053381357342005

正常版本和“缓存”版本之间似乎没有什么区别。为什么?也许默认情况下,Python会缓存在模块,函数和类中定义的不可变对象?

编辑:此外,还有一个奇怪的事实:代码

timeit.timeit("g()", globals={"g": g}, number=100000000)

没有给我任何错误。但是我没有将变量a传递给timeit,难道不应该给我一个例外吗?

1 个答案:

答案 0 :(得分:0)

测量性能总是极其棘手,因为涉及许多层,从应用程序代码,运行时环境,所用的pthon解释器,操作系统到裸机(例如CPU缓存)。例如,看看SO question about loop performance

如果我使用python 3.7.3在计算机上运行相同的测试,则会得到以下结果:

4.8285931999998866
5.371130099956645

所以我的情况相差〜10%。如果我再运行一次相同的测试几次,我还将得到以下结果:

4.646976499861921
5.513043400060269

现在,两种实现之间存在〜18%的差异。我可能会再进行几次相同的测试,像您一样得到<1%的差异。

简而言之:衡量性能差异真的很困难,不要轻易相信您的发现。

编辑:广告“奇怪的事实”:我认为您不需要将a传递给timeit,因为调用g()确实可以无论如何都不访问传递的变量,而是在函数定义期间引用的变量。验证:以下代码不会引发异常:

a = 'hi'
def t():
    if a == 'a':
        raise Exception()
timeit.timeit("t()", globals={"t": t, "a": "a"}, number=1000000)