list_resize(PyListObject *self, Py_ssize_t newsize) { ... if (allocated >= newsize && newsize >= (allocated >> 1)) { assert(self->ob_item != NULL || newsize == 0); Py_SET_SIZE(self, newsize); return0; } /* 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(). * Add padding to make the allocated size multiple of 4. * The growth pattern is: 0, 4, 8, 16, 24, 32, 40, 52, 64, 76, ... * Note: new_allocated won't overflow because the largest possible value * is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t. */ new_allocated = ((size_t)newsize + (newsize >> 3) + 6) & ~(size_t)3; ... }
/* Since the Python memory allocator has granularity of 16 bytes on 64-bit * platforms (8 on 32-bit), there is no benefit of allocating space for * the odd number of items, and there is no drawback of rounding the * allocated size up to the nearest even number. */ size = (size + 1) & ~(size_t)1; PyObject **items = PyMem_New(PyObject*, size); if (items == NULL) { PyErr_NoMemory(); return-1; } self->ob_item = items; self->allocated = size; return0; }