在PyPy下使用__slots__

时间:2014-04-14 18:58:31

标签: python performance pypy slots

我有这个简单的代码帮助我衡量__slots__的课程表现如何(取自here):

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秒左右得到一些东西 - 好吧,它比没有插槽时更快(并且内存效率更高)。

但是,如果我在PyPy下运行代码(使用2.2.1 - 64位用于Mac OS / X),它开始使用100%CPU和#34;从不"返回(等待几分钟 - 没有结果)。

发生了什么事?我应该在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 s:

,则会出现相同的行为
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 个答案:

答案 0 :(得分:11)

timeit代码的10,000次左右迭代中,每次从头开始重新创建该类。在PyPy中创建类可能不是一个优化良好的操作;更糟糕的是,这样做可能会放弃JIT所学到的关于该类之前版本的所有优化。在JIT预热之前,PyPy往往很慢,因此做一些需要它反复预热的事情会使你的表现无效。

这里的解决方案当然是简单地将类定义移到被基准测试的代码之外。

答案 1 :(得分:8)

直接回答标题中的问题:__slots__对于PyPy中的表现毫无意义(但不会造成伤害)。