【发布时间】:2016-08-01 23:59:59
【问题描述】:
我正在修改 Python 的 set 和 frozenset 集合类型。
最初,我认为frozenset 会提供比set 更好的查找性能,因为它是不可变的,因此可以利用存储项目的结构。
但是,关于以下实验,情况似乎并非如此:
import random
import time
import sys
def main(n):
numbers = []
for _ in xrange(n):
numbers.append(random.randint(0, sys.maxint))
set_ = set(numbers)
frozenset_ = frozenset(set_)
start = time.time()
for number in numbers:
number in set_
set_duration = time.time() - start
start = time.time()
for number in numbers:
number in frozenset_
frozenset_duration = time.time() - start
print "set : %.3f" % set_duration
print "frozenset: %.3f" % frozenset_duration
if __name__ == "__main__":
n = int(sys.argv[1])
main(n)
我使用 CPython 和 PyPy 执行了这段代码,结果如下:
> pypy set.py 100000000
set : 6.156
frozenset: 6.166
> python set.py 100000000
set : 16.824
frozenset: 17.248
在 CPython 和 PyPy 中,frozenset 的查找性能似乎实际上更慢。有人知道为什么会这样吗?我没有研究实现。
【问题讨论】:
-
“因为它是不可变的,因此可以利用存储项目的结构” - 你到底期望它做什么?它可以访问的任何结构,
set也可以访问。 -
嗯,这就是我要问的。我想也许 freezeset 可以使用某种预先计算的哈希函数,这反过来可以产生更好的查找性能。
-
您需要计算您查找的任何项目的哈希值,句号。您不能在此处预先计算哈希值,因为您可以针对该集合测试任意项目。我不确定您如何看待这种优化? in 集合中的项目不需要计算其哈希值;它们已经被放入哈希表中。
-
"你需要计算你查找的任何项目的哈希,期间" 我知道这个事实,但仍然有一组固定的元素可以提供优化机会(例如,一个完美的哈希函数可以在生成frozenset的时候生成,可以用于查找)
-
我同意 Sven 的观点,即通过在创建时进行更多计算,从理论上讲,frozenset 可以在查找时表现更好。例如,对于哈希表实现,可以选择一个哈希函数,以便集合元素的哈希之间的冲突最小。
标签: python performance set frozenset