为什么在Python中创建一个类实例比一类是又慢?(Why is creating a class

2019-07-28 21:12发布

我发现一个类的创作是不是类的实例方法要慢。

>>> from timeit import Timer as T
>>> def calc(n):
...     return T("class Haha(object): pass").timeit(n)

<<After several these 'calc' things, at least one of them have a big number, eg. 100000>>

>>> calc(9000)
15.947055101394653
>>> calc(9000)
17.39099097251892
>>> calc(9000)
18.824054956436157
>>> calc(9000)
20.33335590362549

是啊,创造9000班用了16秒,而变得更慢的后续调用。

还有这个:

>>> T("type('Haha', b, d)", "b = (object, ); d = {}").timeit(9000)

给出了相似的结果。

但是实例不吃亏:

>>> T("Haha()", "class Haha(object): pass").timeit(5000000)
0.8786070346832275

5000000个实例在小于一秒钟。

是什么让创建这个贵吗?

为什么在创建过程变得慢一点吗?

编辑:

如何重现:

开始新的蟒过程中,初始数“计算(10000)” S给我的机器上的若干0.5。 并尝试一些较大的值,钙(100000),它不能在连10secs结束,中断它,钙(10000),给出了15秒。

编辑:

其他事实:

如果您GC.Collect的()后,“计算”变得缓慢,你可以在开始时的“正常”的速度,但时间将在随后的呼声越来越高

>>> from a import calc
>>> calc(10000)
0.4673938751220703
>>> calc(10000)
0.4300072193145752
>>> calc(10000)
0.4270968437194824
>>> calc(10000)
0.42754602432250977
>>> calc(10000)
0.4344758987426758
>>> calc(100000)
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "a.py", line 3, in calc
    return T("class Haha(object): pass").timeit(n)
  File "/usr/lib/python2.7/timeit.py", line 194, in timeit
    timing = self.inner(it, self.timer)
  File "<timeit-src>", line 6, in inner
KeyboardInterrupt
>>> import gc
>>> gc.collect()
234204
>>> calc(10000)
0.4237039089202881
>>> calc(10000)
1.5998330116271973
>>> calc(10000)
4.136359930038452
>>> calc(10000)
6.625348806381226

Answer 1:

Ahahaha! 疑难杂症!

是这样或许对Python版本没有做这个补丁 ? (提示:IT WAS)

检查的行号,如果你想证明。

马辛是正确的 :当结果看上去扭曲你可能已经有了一个扭曲的基准。 运行gc.disable()和结果进行自我复制。 它只是表明,当您禁用垃圾收集你的垃圾结果!


为了更清晰,运行长基准爆出了事情的原由是:

  • timeit禁用垃圾收集,所以过大的基准,采取多(成倍)长

  • timeit没有例外恢复垃圾收集

  • 您退出长期运行的进程与异步异常,关闭垃圾回收



Answer 2:

这可能会给你的直觉:

>>> class Haha(object): pass
...
>>> sys.getsizeof(Haha)
904
>>> sys.getsizeof(Haha())
64

类对象是比类的实例更加复杂和昂贵的结构。



Answer 3:

以下功能快速DIS:

def a():
    class Haha(object):
         pass



def b():
    Haha()

得到:

2           0 LOAD_CONST               1 ('Haha')
            3 LOAD_GLOBAL              0 (object)
            6 BUILD_TUPLE              1
            9 LOAD_CONST               2 (<code object Haha at 0x7ff3e468bab0, file "<stdin>", line 2>)
            12 MAKE_FUNCTION            0
            15 CALL_FUNCTION            0
            18 BUILD_CLASS         
            19 STORE_FAST               0 (Haha)
            22 LOAD_CONST               0 (None)
            25 RETURN_VALUE        

2           0 LOAD_GLOBAL              0 (Haha)
            3 CALL_FUNCTION            0
            6 POP_TOP             
            7 LOAD_CONST               0 (None)
            10 RETURN_VALUE        

因此。

通过它的外观,它创建一个类时,简单地做更多的东西。 它初始化类,把它添加到类型的字典和任何其他地方,而在的情况下, Haha()仅仅是调用一个函数。

当你发现做垃圾回收时,它得到太慢速度再次东西了,所以马辛在说,它可能是内存碎片问题的权利。



Answer 4:

这不是 :只有您做作的测试表明慢班创作。 事实上,作为@Veedrac显示了他的答案,这样的结果是timeit禁用垃圾收集的神器。

Downvoters:给我一个不做作的例子,其中类的创建较慢。

在任何情况下,你的时序由当时系统上的负载的影响。 实际上他们只是在几乎相同的时间进行比较有用。 我得到了9000类作品约0.5秒。 事实上,这是对ideone约0.3秒,即使反复进行: http://ideone.com/Du859 。 甚至没有上升的趋势。

因此,简言之,它就是你的电脑比别人的慢得多,并没有向上在其他计算机上进行反复测试趋势(按你原来的要求)。 测试实例的庞大的数字确实显示放缓,这可能是因为该过程消耗大量的内存。 您已经表明,分配大量的内存减慢的过程了。 做得好。

在充满了ideone代码:

from timeit import Timer as T
def calc(n):
return T("class Haha(object): pass").timeit(n)

for i in xrange(30):
print calc(9000)


文章来源: Why is creating a class in Python so much slower than instantiating a class?