【问题标题】:"Caching" a string: why has no effect?“缓存”一个字符串:为什么没有效果?
【发布时间】:2019-10-17 09:42:51
【问题描述】:

我尝试了一个小测试:

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,应该不会给我一个例外吧?

【问题讨论】:

  • 如果你添加它作为答案,我会接受它。

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


【解决方案1】:

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

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

4.8285931999998866
5.371130099956645

所以在我的情况下存在 ~10% 的差异。如果我多次运行相同的测试,我也会得到以下结果:

4.646976499861921
5.513043400060269

现在两种实现之间存在 ~18% 的差异。我可能可以再运行几次相同的测试并得到

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

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

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

【讨论】:

    猜你喜欢
    • 2015-07-24
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    相关资源
    最近更新 更多