Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why there's the difference between creating class in python 2.7 and python 3.4 performance

from timeit import Timer as T

def calc(n):
    return T("class CLS(object): pass").timeit(n)

print(calc(90000))
print(calc(90000))
print(calc(90000))

# python3.4
1.1714721370008192
1.0723806529986177
1.111804607000522

# python2.7
15.7533519268
16.7191421986
16.8397979736

Why is there so much difference in class creation time using different versions of python? Tested on the same machine:

  • i5-3450 CPU @ 3.10GHz
  • 8gb ram
like image 855
Igor Avatar asked Nov 03 '14 11:11

Igor


1 Answers

timeit disables the garbage collector, which would otherwise break the cycles that keep a class object alive. Thus none of the classes gets deallocated until after timeit has finished.

object.__subclasses__() references these classes via an internal collection of weak references. The old list-based implementation of tp_subclasses searches the entire list each time to find a dead reference that can be replaced. This process takes more time with each additional subclass. On the other hand, the new dict-based design in 3.4 can add a reference in constant time. See issue 17936.


Thanks to @MichaelYounkin for pointing out how this is also slow in 3.2. Initially I tried to narrow the performance difference to a change in the small-object allocator between 2.x and 3.x, but after reading his comment I discovered that even 3.3 was considerably slower than 3.4. So I scanned over the typeobject.c filelog to review recent changes.

like image 130
Eryk Sun Avatar answered Oct 12 '22 05:10

Eryk Sun