It's ok to __slots__ for what they were intended

Chris Mellon arkanes at gmail.com
Fri Dec 21 16:49:59 EST 2007


On Dec 21, 2007 2:07 PM, Fredrik Lundh <fredrik at pythonware.com> wrote:
> John Nagle wrote:
>
> >      I'd like to hear more about what kind of performance gain can be
> > obtained from "__slots__".  I'm looking into ways of speeding up
> > HTML parsing via BeautifulSoup.  If a significant speedup can be
> > obtained when navigating large trees of small objects, that's worth
> > quite a bit to me.
>
> The following micro-benchmarks are from Python 2.5 on a Core Duo
> machine.  C0 is an old-style class, C1 is a new-style class, C2 is a
> new-style class using __slots__:
>
> # read access
> $ timeit -s "import q; o = q.C0(); o.attrib = 1" "o.attrib"
> 10000000 loops, best of 3: 0.133 usec per loop
> $ timeit -s "import q; o = q.C1(); o.attrib = 1" "o.attrib"
> 10000000 loops, best of 3: 0.184 usec per loop
> $ timeit -s "import q; o = q.C2(); o.attrib = 1" "o.attrib"
> 10000000 loops, best of 3: 0.161 usec per loop
>
> # write access
> $ timeit -s "import q; o = q.C0(); o.attrib = 1" "o.attrib = 1"
> 10000000 loops, best of 3: 0.15 usec per loop
> $ timeit -s "import q; o = q.C1(); o.attrib = 1" "o.attrib = 1"
> 1000000 loops, best of 3: 0.217 usec per loop
> $ timeit -s "import q; o = q.C2(); o.attrib = 1" "o.attrib = 1"
> 1000000 loops, best of 3: 0.209 usec per loop
>
> $ more q.py
> class C0:
>      pass
>
> class C1(object):
>      pass
>
> class C2(object):
>      __slots__ = ["attrib"]
>
> Your mileage may vary.
>


Here are my timings of object creation time. Note that as you add
slots, the speed advantage disappears.

C:\>python -m timeit -s "from objs import C0 as c" "c()"
1000000 loops, best of 3: 0.298 usec per loop

C:\>python -m timeit -s "from objs import C1 as c" "c()"
10000000 loops, best of 3: 0.172 usec per loop

C:\>python -m timeit -s "from objs import C2 as c" "c()"
10000000 loops, best of 3: 0.164 usec per loop

C:\>python -m timeit -s "from objs import C3 as c" "c()"
1000000 loops, best of 3: 0.302 usec per loop

#objs.py
import string

class C0:
    pass

class C1(object):
    pass

class C2(object):
    __slots__ = ["foo"]

class C3(object):
    __slots__ = list(string.ascii_letters)



More information about the Python-list mailing list