Open aoaoluming opened 2 months ago
translate comment:
static PyObject *
Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
CustomObject *self;
// Call object.tp_new directly, but be careful not to pass args directly to PyBaseObject_Type.tp_new. If you pass args directly, you will get an error when `__init__` is called with parameters.
static PyObject* intern_tuple0 = NULL;
if (intern_tuple0 == NULL)
intern_tuple0 = PyTuple_New(0);
self = PyBaseObject_Type.tp_new(type, intern_tuple0, NULL);
//self = (CustomObject *) type->tp_alloc(type, 0);
Documentation
For Python 3.11 and later, refer to: https://github.com/faster-cpython/ideas/issues/80 (implementation details in CPython source:
_PyObject_InitializeDict
) https://www.youtube.com/watch?v=xKk7IXm0XO0 The memory structure of the Python object dict pointer (dict ptr
) is optimized:However, in CPython directory
Doc/includes/newtypes
, the C extern example that involves adding a__dict__
, such as:still uses the old
dict ptr
structure (prior to Python 3.10).This involves two issues:
dict ptr
structure uses the previous type (as stated above)dict ptr
memory optimization in Python 3.11 and later does not work in the C extern example:The memory optimization in
_PyObject_InitializeDict->init_inline_values
is not utilized:When objects are created in large quantities, the memory per single object can differ by nearly 200 ~ 300bytes 。
detail
### memory of ItemData2 = 392 bytes ``` typedef struct { PyObject_HEAD } CustomObject; # remove custom2.c CustomObject field: first, last, number ``` "The memory size allocated for `new_values` as `PyDictValues` is determined by arg `size` 。 ![image](https://github.com/user-attachments/assets/871263e2-424d-49d4-aaa0-a2f63eb9614d) arg `size` default value is 30(when the `__dict__` contains fewer than 30 members): ![image](https://github.com/user-attachments/assets/8bfe00c0-2787-4852-bd47-5ecf957b4bf9) When arg `size` is 30, the memory size of `PyDictValues` is 272 bytes:" ![image](https://github.com/user-attachments/assets/eb29d70c-952c-4341-8ad5-6e6c9bc68c8e) total size: ``` 56(object ptr basic) + 64(dict ptr) + 0(cache key ptr, shared memory) + 272(values ptr) = 392 bytes ``` ### memory of ItemData = 104 bytes when the `__dict__` contains 2 memebers: ``` memory of values ptr = prefix_size + size * sizeof(PyObject*) = prefix_size + (dk_entries + dk_usable) * sizeof(PyObject*) = 32 + (2 + 0) * 8 = 48 bytes 56(object basic memory) + 0(dict ptr) + 0(cache key, shared) + 48(value ptr)= 104 bytes ```I try to fix it, like: