在PyPy中使用__slots__
我有一段简单的代码,用来测量带有 __slots__
的类的性能(这个代码来自 这里):
import timeit
def test_slots():
class Obj(object):
__slots__ = ('i', 'l')
def __init__(self, i):
self.i = i
self.l = []
for i in xrange(1000):
Obj(i)
print timeit.Timer('test_slots()', 'from __main__ import test_slots').timeit(10000)
如果我在 python2.7 下运行这段代码,结果大约是 6 秒 - 嗯,确实比没有使用 slots 的情况快很多(而且也更省内存)。
但是,如果我在 PyPy 下运行这段代码(使用的是 2.2.1 - 64位的 Mac OS/X),它就开始占用 100% 的 CPU,而且“永远”不会返回结果(我等了好几分钟 - 还是没有结果)。
这是怎么回事?我在 PyPy 下应该使用 __slots__
吗?
如果我给 timeit()
传入不同的数字,会发生什么呢:
timeit(10) - 0.067s
timeit(100) - 0.5s
timeit(1000) - 19.5s
timeit(10000) - ? (probably more than a Game of Thrones episode)
提前谢谢你。
注意,如果我使用 namedtuple
,也会出现同样的情况:
import collections
import timeit
def test_namedtuples():
Obj = collections.namedtuple('Obj', 'i l')
for i in xrange(1000):
Obj(i, [])
print timeit.Timer('test_namedtuples()', 'from __main__ import test_namedtuples').timeit(10000)
2 个回答
8
直接回答标题中的问题:__slots__
在 PyPy 中对性能没有什么意义(但也不会造成伤害)。
12
在大约10,000次的timeit
代码运行中,每次都会重新创建这个类。创建类的过程在PyPy中可能不是很高效;更糟糕的是,这样做可能会丢掉JIT(即时编译器)对之前类的优化信息。PyPy在JIT还没有完全准备好之前通常会比较慢,所以如果你频繁做需要它准备好的事情,就会严重影响性能。
解决这个问题的方法很简单,就是把类的定义放到被测试代码之外。