Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Что внутри у питона: как устроена память

Что внутри у питона: как устроена память

Злата Обуховская (Teamlead в Nvidia, евангелист MoscowPython) @ MoscowPython Meetup 63

"В этой части докладов про внутренности питона мы посмотрим, как происходит выделение памяти, как работают счетчики ссылок, кэши объектов и сборка мусора, а также разберемся, причем тут GIL".

Видео: http://www.moscowpython.ru/meetup/63/python-memory/

Moscow Python Meetup

February 08, 2019
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. char *src = malloc(len); char *dst = malloc(len); src =

    scanf("%s", len); dst = memcpy(dst, src, len); ... free(src); free(dst); def foo(): src = input() dst = src
  2. int PyByteArray_Resize(PyObject *self, Py_ssize_t requested_size) { ... sval = PyObject_Malloc(alloc);

    memcpy(sval, PyByteArray_AS_STRING(self), Py_MIN((size_t)requested_size, (size_t)Py_SIZE(self))); PyObject_Free(obj->ob_bytes); obj->ob_bytes = obj->ob_start = sval;
  3. _____ ______ ______ ________ [ int ] [ dict ]

    [ list ] ... [ string ] Python core | +3 | <----- Object-specific memory -----> | <-- Non-object memory --> | _______________________________ | | [ Python's object allocator ] | | +2 | ####### Object memory ####### | <------ Internal buffers ------> | ______________________________________________________________ | [ Python's raw memory allocator (PyMem_ API) ] | +1 | <----- Python memory (under PyMem manager's control) ------> | | __________________________________________________________________ [ Underlying general-purpose allocator (ex: C library malloc) ] 0 | <------ Virtual memory allocated for the python process -------> |
  4. _____ ______ ______ ________ [ int ] [ dict ]

    [ list ] ... [ string ] Python core | +3 | <----- Object-specific memory -----> | <-- Non-object memory --> | _______________________________ | | [ Python's object allocator ] | | +2 | ####### Object memory ####### | <------ Internal buffers ------> | ______________________________________________________________ | [ Python's raw memory allocator (PyMem_ API) ] | +1 | <----- Python memory (under PyMem manager's control) ------> | | __________________________________________________________________ [ Underlying general-purpose allocator (ex: C library malloc) ] 0 | <------ Virtual memory allocated for the python process -------> |
  5. static void * _PyObject_Malloc(void *ctx, size_t nbytes) { void* ptr;

    if (pymalloc_alloc(ctx, &ptr, nbytes)) { _Py_AllocatedBlocks++; return ptr; } ptr = PyMem_RawMalloc(nbytes); if (ptr != NULL) { _Py_AllocatedBlocks++; } return ptr; }
  6. static int pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) { ...

    if (nbytes > SMALL_REQUEST_THRESHOLD) { return 0; } ... ...
  7. * Request in bytes Size of allocated block Size class

    idx * ---------------------------------------------------------------- * 1-8 8 0 * 9-16 16 1 * 17-24 24 2 * 25-32 32 3 * 33-40 40 4 * 41-48 48 5 * 49-56 56 6 * 57-64 64 7 * 65-72 72 8 * ... ... ... * 497-504 504 62 * 505-512 512 63
  8. TARGET(LOAD_CONST) { PyObject *value = GETITEM(consts, oparg); Py_INCREF(value); PUSH(value); FAST_DISPATCH();

    } TARGET(POP_TOP) { PyObject *value = POP(); Py_DECREF(value); FAST_DISPATCH(); }
  9. #define Py_DECREF(op) do { PyObject *_py_decref_tmp = (PyObject *)(op); if

    (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA --(_py_decref_tmp)->ob_refcnt != 0) _Py_CHECK_REFCNT(_py_decref_tmp) else _Py_Dealloc(_py_decref_tmp); } while (0)
  10. void PyObject_GC_Del(void *op) { PyGC_Head *g = AS_GC(op); if (IS_TRACKED(op))

    gc_list_remove(g); if (_PyRuntime.gc.generations[0].count > 0) _PyRuntime.gc.generations[0].count--; } PyObject_FREE(g); }
  11. PyObject * _PyObject_GC_Alloc(int use_calloc, size_t basicsize) { PyObject *op; PyGC_Head

    *g; size_t size; ... size = sizeof(PyGC_Head) + basicsize; ... g = (PyGC_Head *)PyObject_Malloc(size); ... _PyGCHead_SET_REFS(g, GC_UNTRACKED); ... op = FROM_GC(g); return op; }
  12. typedef union _gc_head { struct { union _gc_head *gc_next; union

    _gc_head *gc_prev; Py_ssize_t gc_refs; } gc; double dummy; /* force worst-case alignment */ } PyGC_Head;