[Tutor] object size in python is in what units?

Oscar Benjamin oscar.j.benjamin at gmail.com
Tue Jul 23 16:21:47 CEST 2013


On 23 July 2013 09:13, Marc Tompkins <marc.tompkins at gmail.com> wrote:
>
> As an experiment, I added a couple of extra methods and attributes to the
> Kronk class, but it didn't change anything - IDs still incremented by 40
> each time.  eryksun will no doubt chime in to tell us exactly how object IDs
> are derived in cPython, but I'll go out on a limb and say that they have
> nothing to do with the size of the object; also that one would be very silly
> to make a program rely in any way on predicting the next ID, since external
> factors may throw off the calculations (as when I invoked your original
> script from inside PyScripter).  All that you can rely on is that each
> unique object (i.e. doesn't pass an "is" comparison with any other object)
> has a unique ID... and, for all I know, not even that.
>

It has been pointed out that the value returned by id() should not be
considered as a memory address since it isn't always a memory address
in every Python implementation. However in CPython it is just the
memory address i.e. the numeric value of the PyObject* pointer for the
object.

The reason for the patterns that you observe are related to CPython's
memory pool allocator. You can read the long source comment describing
this here:
http://hg.python.org/cpython/file/a5681f50bae2/Objects/obmalloc.c#l367

Essentially anything over 512 bytes will be allocated using a call to
the system (OS/runtime) malloc. Anything under 512 bytes will be
allocated into a memory pool managed by the interpreter. The code I
linked to shows the exact strategy used for this and if you read this
you'll have a vague understanding of the results you see.

You can check the size in bytes of an object with sys.getsizeof e.g.:

>>> import sys
>>> sys.getsizeof(lardKronk)
36

Note that I'm running Python 2.7, Windows XP, 32-bit to get that
result and it is different on different platforms.

So the size was 36 bytes but I also get the spacing of 40 bytes (when
I run your script with 'python kronk.py').
The reason I get a spacing of 40 when only 36 bytes are needed for
each allocation is that allocation uses 8-byte alingment so everything
works in multiples of 8. This is described/defined here:
http://hg.python.org/cpython/file/a5681f50bae2/Objects/obmalloc.c#l471

The reason that you get different results when running from pyscripter
(it's the same with ipython) is presumably that in order to initialise
pyscripter the interpreter will perform lots of other allocations
before running your script. Consequently it will likely have lots of
half-full memory pools with spaces that can fit a Kronk allocation
here and there and uses those before creating a new pool. When you
just run it as python kronk.py a lot less happens before your script
runs.


Oscar


More information about the Tutor mailing list