【发布时间】:2015-06-12 22:00:28
【问题描述】:
我正在编写一个井字游戏并使用枚举来表示三个结果——lose、draw 和win。我认为这会比使用字符串("lose", "win", "draw") 来指示这些值更好。但是使用枚举给了我很大的性能损失。
这是一个最小的例子,我只是引用 Result.lose 或文字字符串 lose。
import enum
import timeit
class Result(enum.Enum):
lose = -1
draw = 0
win = 1
>>> timeit.timeit('Result.lose', 'from __main__ import Result')
1.705788521998329
>>> timeit.timeit('"lose"', 'from __main__ import Result')
0.024598151998361573
这比简单地引用全局变量要慢得多。
k = 12
>>> timeit.timeit('k', 'from __main__ import k')
0.02403248500195332
我的问题是:
- 我知道在 Python 中全局查找比本地查找慢得多。但为什么枚举查找更糟糕?
- 如何在不牺牲性能的情况下有效地使用枚举?事实证明,枚举查找完全支配了我的井字游戏程序的运行时间。我们可以在每个函数中保存枚举的本地副本,或者将所有内容包装在一个类中,但这两种方法都显得笨拙。
【问题讨论】:
-
我认为可能是属性检索速度慢。如果您执行
lose = Result.lose之类的操作,然后针对lose进行测试,无论是本地的还是全局的,我认为您会看到可衡量的加速。 -
谢谢,效果很好。你知道为什么属性查找比全局查找慢得多吗?我知道局部变量存储在一个固定长度的数组中,而全局变量存储在一个字典中,但是与属性有什么关系呢?
-
我不知道,抱歉。如果不阅读 CPython 源代码,我无法确定地告诉你任何事情。如果我不得不猜测,我会说对象是用关联数组或映射或任何底层实现的(只是一种可能性,不被视为事实),因此属性名称上使用的散列算法可能会有成本这就像哈希表的字符串键,但这都是猜测。无论如何,您现在知道如何在重复查找的情况下将其最小化。本地化ftw。
-
枚举属性查找非常慢的事实实际上是一个性能错误:bugs.python.org/issue23486,在 Python 3.5 中,这被加速了很多(慢了 3 倍而不是慢了 20 倍)
标签: python performance enums python-3.4