Python size of list in bytes

Here's a fuller interactive session that will help me explain what's going on [Python 2.6 on Windows XP 32-bit, but it doesn't matter really]:

>>> import sys
>>> sys.getsizeof[[]]
36
>>> sys.getsizeof[[1]]
40
>>> lst = []
>>> lst.append[1]
>>> sys.getsizeof[lst]
52
>>> 

Note that the empty list is a bit smaller than the one with [1] in it. When an element is appended, however, it grows much larger.

The reason for this is the implementation details in Objects/listobject.c, in the source of CPython.

Empty list

When an empty list [] is created, no space for elements is allocated - this can be seen in PyList_New. 36 bytes is the amount of space required for the list data structure itself on a 32-bit machine.

List with one element

When a list with a single element [1] is created, space for one element is allocated in addition to the memory required by the list data structure itself. Again, this can be found in PyList_New. Given size as argument, it computes:

nbytes = size * sizeof[PyObject *];

And then has:

if [size ob_item = NULL;
else {
    op->ob_item = [PyObject **] PyMem_MALLOC[nbytes];
    if [op->ob_item == NULL] {
        Py_DECREF[op];
        return PyErr_NoMemory[];
    }
    memset[op->ob_item, 0, nbytes];
}
Py_SIZE[op] = size;
op->allocated = size;

So we see that with size = 1, space for one pointer is allocated. 4 bytes [on my 32-bit box].

Appending to an empty list

When calling append on an empty list, here's what happens:

  • PyList_Append calls app1
  • app1 asks for the list's size [and gets 0 as an answer]
  • app1 then calls list_resize with size+1 [1 in our case]
  • list_resize has an interesting allocation strategy, summarized in this comment from its source.

Here it is:

/* This over-allocates proportional to the list size, making room
* for additional growth.  The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends[] in the presence of a poorly-performing
* system realloc[].
* The growth pattern is:  0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
new_allocated = [newsize >> 3] + [newsize < 9 ? 3 : 6];

/* check for integer overflow */
if [new_allocated > PY_SIZE_MAX - newsize] {
    PyErr_NoMemory[];
    return -1;
} else {
    new_allocated += newsize;
}

Let's do some math

Let's see how the numbers I quoted in the session in the beginning of my article are reached.

So 36 bytes is the size required by the list data structure itself on 32-bit. With a single element, space is allocated for one pointer, so that's 4 extra bytes - total 40 bytes. OK so far.

When app1 is called on an empty list, it calls list_resize with size=1. According to the over-allocation algorithm of list_resize, the next largest available size after 1 is 4, so place for 4 pointers will be allocated. 4 * 4 = 16 bytes, and 36 + 16 = 52.

Indeed, everything makes sense :-]

View Discussion

Improve Article

Save Article

  • Read
  • Discuss
  • View Discussion

    Improve Article

    Save Article

    In Python, a list is a collection data type that can store elements in an ordered manner and can also have duplicate elements. The size of a list means the amount of memory [in bytes] occupied by a list object. In this article, we will learn various ways to get the size of a python list.

    1.Using getsizeof[] function:

    The getsizeof[] function belongs to the python’s sys module. It has been implemented in the below example.

    Example 1:

    import sys

    list1 = [1, 2, 3, 5]

    list2 = ["GeeksForGeeks", "Data Structure", "Algorithms"]

    list3 = [1, "Geeks", 2, "For", 3, "Geeks"]

    print["Size of list1: " + str[sys.getsizeof[list1]] + "bytes"]

    print["Size of list2: " + str[sys.getsizeof[list2]] + "bytes"]

    print["Size of list3: " + str[sys.getsizeof[list3]] + "bytes"]

    Output:

    Size of list1: 96bytes
    Size of list1: 88bytes
    Size of list1: 112bytes

    Note:The sys.getsizeof[] function includes the marginal space usage, which includes the garbage collection overhead for the object. Meaning it returns the total space occupied by the object in addition to the garbage collection overhead for the spaces being used.

    1.Using inbuilt __sizeof__[] method:

    Python also has an inbuilt __sizeof__[] method to determine the space allocation of an object without any additional garbage value. It has been implemented in the below example.
    Example 2:

    list1 = [1, 2, 3, 5]

    list2 = ["GeeksForGeeks", "Data Structure", "Algorithms"]

    list3 = [1, "Geeks", 2, "For", 3, "Geeks"]

    print["Size of list1: " + str[list1.__sizeof__[]] + "bytes"]

    print["Size of list2: " + str[list2.__sizeof__[]] + "bytes"]

    print["Size of list3: " + str[list3.__sizeof__[]] + "bytes"]

    Output:

    Size of list1: 72bytes
    Size of list1: 64bytes
    Size of list1: 88bytes

    How many bytes is a Python list?

    A list that contains a long string takes just 64 bytes.

    How do you find the size of a list in Python?

    Python has got in-built method – len[] to find the size of the list i.e. the length of the list. The len[] method accepts an iterable as an argument and it counts and returns the number of elements present in the list.

    How do I check memory list size?

    In order to determine the size of the list, we have passed the list object to the getsizeof[] function which on execution return the sizes of list1 and list2 in bytes along with garbage collector overhead. List1 and list2 are occupying 112 bytes and 104 bytes in the memory.

    What is __ sizeof __ in Python?

    The __sizeof__[] function in Python doesn't exactly tell us the size of the object. It doesn't return the size of a generator object as Python cannot tell us beforehand that how much size of a generator is. Still, in actuality, it returns the internal size for a particular object [in bytes] occupying the memory.

    Chủ Đề