__slots__

Mirko Zeibig mirko-lists at zeibig.net
Mon Dec 8 07:16:26 EST 2003


On Wed, 12 Nov 2003 at 04:52 GMT, Patrick Maupin <pmaupin at speakeasy.net> wrote:
> Brad Clements wrote:
> 
>> But nonetheless I slotted myself into a corner anyway. Now I have to undo
>> all those nasty slots statements.
>> 
>> My advice.. forget __slots__!
>
> One might also find, while taking this path, that the
> use of __slots__ by itself makes SOME applications run
> fast enough without going all the way to Pyrex.  At this
> point, one might reasonably conclude (despite the
> oft-repeated claim that __slots__ are an un-Pythonic
> "premature optimization") that the ability to avoid writing
> a C extension by merely adding a single line of (basically
> non-executable) code to a class or two is unalloyed goodness.

Just as an info: I ran some tests using slots vs. "normal classes" vs. tuples,
here are the definitions for the classes:

class NoSlots(object):
    def __init__(self, *args):
        self.id, self.weight = args

class Slots(object):
    __slots__ = ('id', 'weight')
    def __init__(self, *args):
        self.id, self.weight = args

def createtuple(id, weight):
    return (id, weight)

def create(func, count):
    w = timer.create("creating %s" % func)
    l = [ func(str(id), id*2) for id in xrange(count) ]
    w.stop()
    showMemUsage(func)
    return l

def usetupledirectly(func, count):
    w = timer.create("creating %s" % func)
    l = [ (str(id), id*2) for id in xrange(count) ]
    w.stop()
    showMemUsage(func)
    return l


created lot's of these and hold them in a list. I measured memory-usage very
roughly using /proc/self/status (VmRSS):

[mize at lxmize python]$ for i in 1000 10000 100000 ; do ./memusage_speed_tuple_vs_simple_classes.py $i; done
********************************************************************************
Creating 1000 objects
MemUsage               <class '__main__.NoSlots'>: 2780 kB
MemUsage                 <class '__main__.Slots'>: 80 kB
MemUsage      <function createtuple at 0x8242214>: 88 kB
MemUsage <function usetupledirectly at 0x8214a84>: 88 kB
   Runtime   UsrTim   SysTim Calls NestC PendC TimerName
     0.216    0.130    0.000     1     0     0 total
     0.039    0.040    0.000     1     0     0 creating <class '__main__.NoSlots'>
     0.035    0.040    0.000     1     0     0 creating <class '__main__.Slots'>
     0.019    0.020    0.000     1     0     0 creating <function createtuple at 0x8242214>
     0.011    0.010    0.000     1     0     0 creating <function usetupledirectly at 0x8214a84>
     0.007    0.010    0.000     1     0     0 deleting stuff, disablegc=0
********************************************************************************
Creating 10000 objects
MemUsage               <class '__main__.NoSlots'>: 4752 kB
MemUsage                 <class '__main__.Slots'>: 800 kB
MemUsage      <function createtuple at 0x8242214>: 860 kB
MemUsage <function usetupledirectly at 0x8214a84>: 864 kB
   Runtime   UsrTim   SysTim Calls NestC PendC TimerName
     1.351    1.230    0.020     1     0     0 total
     0.438    0.440    0.000     1     0     0 creating <class '__main__.NoSlots'>
     0.365    0.370    0.000     1     0     0 creating <class '__main__.Slots'>
     0.186    0.180    0.000     1     0     0 creating <function createtuple at 0x8242214>
     0.148    0.130    0.020     1     0     0 creating <function usetupledirectly at 0x8214a84>
     0.100    0.100    0.000     1     0     0 deleting stuff, disablegc=0
********************************************************************************
Creating 100000 objects
MemUsage               <class '__main__.NoSlots'>: 25160 kB
MemUsage                 <class '__main__.Slots'>: 8528 kB
MemUsage      <function createtuple at 0x8242214>: 9308 kB
MemUsage <function usetupledirectly at 0x8214a84>: 9308 kB
   Runtime   UsrTim   SysTim Calls NestC PendC TimerName
    16.979   16.230    0.610     1     0     0 total
     5.448    5.230    0.200     1     0     0 creating <class '__main__.NoSlots'>
     4.792    4.640    0.140     1     0     0 creating <class '__main__.Slots'>
     3.111    2.970    0.140     1     0     0 creating <function createtuple at 0x8242214>
     2.805    2.670    0.130     1     0     0 creating <function usetupledirectly at 0x8214a84>
     0.716    0.710    0.000     1     0     0 deleting stuff, disablegc=0
[mize at lxmize python]$

So while there is a big memory saving in using __slots__, the time savings I
observed are relatively small. Test system is a Pentium Celeron 500MHz with 256
MB running the Python 2.2 on Linux. Of course never trust measurements you
didn't manipulate yourself ;-).

Regards
Mirko




More information about the Python-list mailing list