Управление памятью
Обзор
Управление памятью в Python включает в себя частную кучу, содержащую все объекты и структуры данных Python. Управление этой частной кучей обеспечивается внутренне менеджером памяти Python. У менеджера памяти Python есть разные компоненты, которые занимаются различными аспектами динамического управления хранением, такими как совместное использование, сегментация, предварительная выделение или кэширование.
На самом низком уровне, непосредственный выделения памяти гарантирует, что в частной куче достаточно места для хранения всех данных, связанных с Python, взаимодействуя с менеджером памяти операционной системы. Над непосредственным выделением памяти работают несколько выделений памяти, специфичных для объектов, которые работают с той же кучей и реализуют различные политики управления памятью, адаптированные к особенностям каждого типа объекта. Например, целые числа управляются в куче по-другому, чем строки, кортежи или словари, потому что целые числа предполагают разные требования к хранению и компромиссы между скоростью и размером. Таким образом, менеджер памяти Python делегирует часть работы выделениям памяти, специфичным для объектов, но гарантирует, что последние работают в рамках частной кучи.
Важно понимать, что управление кучей Python выполняется самим интерпретатором, и у пользователя нет контроля над ним, даже если они регулярно манипулируют указателями объектов на блоки памяти внутри этой кучи. Выделение пространства кучи для объектов Python и других внутренних буферов выполняется по требованию менеджером памяти Python с помощью функций Python/C API, перечисленных в данном документе.
Чтобы избежать повреждения памяти, разработчики расширений никогда не должны пытаться взаимодействовать с объектами Python с помощью функций, экспортируемых библиотекой C: malloc(), calloc(), realloc() и free(). Это приведет к смешанным вызовам между выделением памяти C и менеджером памяти Python с фатальными последствиями, потому что они реализуют разные алгоритмы и работают с разными кучами. Однако можно безопасно выделять и освобождать блоки памяти с помощью выделения памяти C для индивидуальных целей, как показано в следующем примере:
PyObject *res;
char *buf = (char *) malloc(BUFSIZ); /* for I/O */
if (buf == NULL)
return PyErr_NoMemory();
...Do some I/O operation involving buf...
res = PyBytes_FromString(buf);
free(buf); /* malloc'ed */
return res;
В этом примере запрос памяти для буфера ввода-вывода обрабатывается выделением памяти C. Менеджер памяти Python участвует только в выделении объекта байтов, возвращаемого в качестве результата.
Однако в большинстве ситуаций рекомендуется выделять память из кучи Python специально, потому что последняя находится под контролем менеджера памяти Python. Например, это необходимо, когда интерпретатор расширяется с помощью новых типов объектов, написанных на C. Другая причина использования кучи Python заключается в стремлении сообщить менеджеру памяти Python о потребностях в памяти модуля расширения. Даже когда запрашиваемая память используется исключительно для внутренних, узкоспециализированных целей, делегирование всех запросов на выделение памяти менеджеру памяти Python позволяет интерпретатору иметь более точное представление о его общем объеме памяти. Следовательно, в определенных обстоятельствах менеджер памяти Python может или не может инициировать соответствующие действия, такие как сборка мусора, уплотнение памяти или другие превентивные процедуры. Обратите внимание, что при использовании выделения памяти библиотеки C, как показано в предыдущем примере, выделенная память для буфера ввода-вывода полностью выходит за пределы менеджера памяти Python.
См. также
Переменная окружения PYTHONMALLOC может использоваться для настройки выделений памяти, используемых Python.
Переменная окружения PYTHONMALLOCSTATS может использоваться для печати статистики выделения памяти выделения памяти pymalloc каждый раз, когда создаётся новая область выделения памяти pymalloc, и при завершении работы.
Области выделения памяти
Все функции выделения памяти принадлежат одному из трех различных «областей» (см. также PyMemAllocatorDomain). Эти области представляют различные стратегии выделения памяти и оптимизированы для разных целей. Детали того, как каждая область выделяет память или какие внутренние функции вызывает каждая область, считаются деталями реализации, но для отладки можно найти упрощенную таблицу по адресу здесь. API, используемые для выделения и освобождения блока памяти, должны быть из одной области. Например, PyMem_Free() должен использоваться для освобождения памяти, выделенной с помощью PyMem_Malloc().
Три области выделения памяти:
- Область непосредственного выделения: предназначена для выделения памяти для буферов памяти общего назначения, когда выделение обязательно должно происходить через выделение памяти операционной системы или когда выделение памяти может выполняться без блокировки GIL. Память запрашивается напрямую у системы. См. Интерфейс непосредственного выделения памяти.
- Область «Mem»: предназначена для выделения памяти для буферов Python и буферов памяти общего назначения, когда выделение должно выполняться с захваченной блокировкой GIL. Память берется из частной кучи Python. См. Интерфейс памяти.
- Область объектов: предназначена для выделения памяти для объектов Python. Память берется из частной кучи Python. См. Выделения памяти объектов.
Примечание
В версии с бесплатной многопоточностью требуется, чтобы только объекты Python выделялись с использованием области «объект», и что все объекты Python выделялись с использованием этой области. Это отличается от предыдущих версий Python, где это было только рекомендацией, а не жестким требованием.
Например, буферы (объекты, не являющиеся объектами Python) должны выделяться с помощью PyMem_Malloc(), PyMem_RawMalloc() или malloc(), но не PyObject_Malloc().
См. API выделения памяти.
Интерфейс необработанной памяти
Следующие наборы функций являются обёртками над системным аллокатором. Эти функции потокобезопасны, не нужно удерживать блокировку интерпретатора.
В по умолчанию используемый аллокатор необработанной памяти используются следующие функции: malloc(), calloc(), realloc() и free(); вызов malloc(1) (или calloc(1, 1)) при запросе нулевого количества байт.
Добавлена в версии 3.4.
-
void *PyMem_RawMalloc(size_t n) -
Часть стабильной ABI с версии 3.13.
Выделяет n байт и возвращает указатель типа void* на выделенную память или
NULLв случае неудачи.Запрос нулевого количества байт возвращает уникальный указатель, не являющийся
NULLуказателем, если это возможно, как если бы был вызванPyMem_RawMalloc(1). Память не будет инициализирована каким-либо образом.
-
void *PyMem_RawCalloc(size_t nelem, size_t elsize) -
Часть стабильной ABI с версии 3.13.
Выделяет nelem элементов, каждый размером elsize байт, и возвращает указатель типа void* на выделенную память или
NULLв случае неудачи. Память инициализируется нулями.Запрос нулевого количества элементов или элементов размером ноль байт возвращает уникальный указатель, не являющийся
NULLуказателем, если это возможно, как если бы был вызванPyMem_RawCalloc(1, 1).Добавлена в версии 3.5.
-
void *PyMem_RawRealloc(void *p, size_t n) -
Часть стабильной ABI с версии 3.13.
Изменяет размер блока памяти, на который указывает p, на n байт. Содержимое останется неизменным в пределах минимального из старого и нового размеров.
Если p равно
NULL, вызов эквивалентенPyMem_RawMalloc(n); в противном случае, если n равно нулю, размер блока памяти изменяется, но он не освобождается, и возвращаемый указатель не являетсяNULL.За исключением случая, когда p равно
NULL, он должен был быть возвращён предыдущим вызовомPyMem_RawMalloc(),PyMem_RawRealloc()илиPyMem_RawCalloc().Если запрос не удаётся,
PyMem_RawRealloc()возвращаетNULL, и p остаётся допустимым указателем на предыдущую область памяти.
-
void PyMem_RawFree(void *p) -
Часть стабильной ABI с версии 3.13.
Освобождает блок памяти, на который указывает p, который должен был быть возвращён предыдущим вызовом
PyMem_RawMalloc(),PyMem_RawRealloc()илиPyMem_RawCalloc(). В противном случае или еслиPyMem_RawFree(p)был вызван ранее, происходит неопределённое поведение.Если p равно
NULL, никакая операция не выполняется.
Интерфейс памяти
Следующие наборы функций, основанные на стандарте ANSI C, но указывающие поведение при запросе нулевого количества байт, доступны для выделения и освобождения памяти из кучи Python.
В по умолчанию используемом аллокаторе памяти используется аллокатор памяти pymalloc.
Предупреждение
Необходимо удерживать блокировку интерпретатора при использовании этих функций.
Изменено в версии 3.6: Аллокатор по умолчанию теперь pymalloc, а не системный malloc().
-
void *PyMem_Malloc(size_t n) -
Часть стабильной ABI.
Выделяет n байт и возвращает указатель типа void* на выделенную память или
NULLв случае неудачи.Запрос нулевого количества байт возвращает уникальный указатель, не являющийся
NULLуказателем, если это возможно, как если бы был вызванPyMem_Malloc(1). Память не будет инициализирована каким-либо образом.
-
void *PyMem_Calloc(size_t nelem, size_t elsize) -
Часть стабильной ABI с версии 3.7.
Выделяет nelem элементов, каждый размером elsize байт, и возвращает указатель типа void* на выделенную память или
NULLв случае неудачи. Память инициализируется нулями.Запрос нулевого количества элементов или элементов размером ноль байт возвращает уникальный указатель, не являющийся
NULLуказателем, если это возможно, как если бы был вызванPyMem_Calloc(1, 1).Добавлена в версии 3.5.
-
void *PyMem_Realloc(void *p, size_t n) -
Часть стабильной ABI.
Изменяет размер блока памяти, на который указывает p, на n байт. Содержимое останется неизменным в пределах минимального из старого и нового размеров.
Если p равно
NULL, вызов эквивалентенPyMem_Malloc(n); в противном случае, если n равно нулю, размер блока памяти изменяется, но он не освобождается, и возвращаемый указатель не являетсяNULL.За исключением случая, когда p равно
NULL, он должен был быть возвращён предыдущим вызовомPyMem_Malloc(),PyMem_Realloc()илиPyMem_Calloc().Если запрос не удаётся,
PyMem_Realloc()возвращаетNULL, и p остаётся допустимым указателем на предыдущую область памяти.
-
void PyMem_Free(void *p) -
Часть стабильной ABI.
Освобождает блок памяти, на который указывает p, который должен был быть возвращён предыдущим вызовом
PyMem_Malloc(),PyMem_Realloc()илиPyMem_Calloc(). В противном случае или еслиPyMem_Free(p)был вызван ранее, происходит неопределённое поведение.Если p равно
NULL, никакая операция не выполняется.
Для удобства предоставляются следующие макросы с ориентацией на типы. Обратите внимание, что TYPE относится к любому типу C.
-
PyMem_New(TYPE, n) -
Аналогично
PyMem_Malloc(), но выделяет(n * sizeof(TYPE))байта памяти. Возвращает указатель, приведённый к типуTYPE*. Память не будет инициализирована каким-либо образом.
-
PyMem_Resize(p, TYPE, n) -
Аналогично
PyMem_Realloc(), но размер блока памяти изменяется на(n * sizeof(TYPE))байт. Возвращает указатель, приведённый к типуTYPE*. При возврате p будет указателем на новую область памяти илиNULLв случае неудачи.Это макрос препроцессора C; p всегда переопределяется. Сохраните исходное значение p, чтобы избежать потери памяти при обработке ошибок.
-
void PyMem_Del(void *p) -
Аналогично
PyMem_Free().
Кроме того, предоставляются следующие наборы макросов для непосредственного вызова аллокатора памяти Python без использования функций API C, перечисленных выше. Однако обратите внимание, что их использование не сохраняет бинарную совместимость между версиями Python и поэтому устарело в модулях расширения.
PyMem_MALLOC(size)PyMem_NEW(type, size)PyMem_REALLOC(ptr, size)PyMem_RESIZE(ptr, type, size)PyMem_FREE(ptr)PyMem_DEL(ptr)
Операторы выделения объектов
Следующие функции, моделирующие стандарт ANSI C, но задающие поведение при запросе нулевого количества байт, доступны для выделения и освобождения памяти из кучи Python.
Примечание
Нет гарантии, что память, возвращаемая этими операторами, может быть успешно преобразована в объект Python при перехвате функций выделения в этом домене методами, описанными в разделе Настройка операторов выделения памяти.
Оператор по умолчанию для выделения объектов использует оператор выделения памяти pymalloc.
Предупреждение
При использовании этих функций необходимо удерживать GIL.
-
void *PyObject_Malloc(size_t n) -
Часть Стабильной ABI.
Выделяет n байт и возвращает указатель типа void* на выделенную память или
NULLв случае неудачи.Запрос на выделение нулевого количества байт возвращает уникальный не-
NULLуказатель, если это возможно, как если бы была вызвана функцияPyObject_Malloc(1). Память не будет инициализирована.
-
void *PyObject_Calloc(size_t nelem, size_t elsize) -
Часть Стабильной ABI с версии 3.7.
Выделяет nelem элементов, каждый размером elsize байт, и возвращает указатель типа void* на выделенную память или
NULLв случае неудачи. Память инициализируется нулями.Запрос на выделение нулевого количества элементов или элементов размером ноль байт возвращает уникальный не-
NULLуказатель, если это возможно, как если бы была вызвана функцияPyObject_Calloc(1, 1).Добавлена в версии 3.5.
-
void *PyObject_Realloc(void *p, size_t n) -
Часть Стабильной ABI.
Изменяет размер блока памяти, на который указывает p, на n байт. Содержимое не изменяется для минимального значения старого и нового размеров.
Если p равно
NULL, вызов эквивалентен вызовуPyObject_Malloc(n); в противном случае, если n равно нулю, размер блока памяти изменяется, но не освобождается, и возвращаемый указатель неNULL.Если p не равно
NULL, оно должно было быть возвращено предыдущим вызовомPyObject_Malloc(),PyObject_Realloc()илиPyObject_Calloc().Если запрос не выполняется,
PyObject_Realloc()возвращаетNULL, и p остается валидным указателем на предыдущую область памяти.
-
void PyObject_Free(void *p) -
Часть Стабильной ABI.
Освобождает блок памяти, на который указывает p, который должен был быть возвращён предыдущим вызовом
PyObject_Malloc(),PyObject_Realloc()илиPyObject_Calloc(). В противном случае, или еслиPyObject_Free(p)было вызвано ранее, происходит неопределённое поведение.Если p равно
NULL, никакая операция не выполняется.
Операторы выделения памяти по умолчанию
Операторы выделения памяти по умолчанию:
Конфигурация | Имя | PyMem_RawMalloc | PyMem_Malloc | PyObject_Malloc |
|---|---|---|---|---|
Сборка релиз |
|
|
|
|
Сборка отладки |
|
|
|
|
Сборка релиз без pymalloc |
|
|
|
|
Сборка отладки без pymalloc |
|
|
|
|
Легенда:
- Имя: значение для переменной окружения
PYTHONMALLOC. -
malloc: системные операторы выделения из стандартной C библиотеки, C функции:malloc(),calloc(),realloc()иfree(). -
pymalloc: оператор выделения памяти pymalloc. -
mimalloc: оператор выделения памяти mimalloc. Если поддержка mimalloc недоступна, будет использоваться оператор pymalloc. - «+ отладка»: с активированными отладочными крючками Python операторов выделения памяти.
- «Сборка отладки»: Сборка Python в режиме отладки.
Настройка механизмов выделения памяти
Добавлен в версии 3.4.
-
type PyMemAllocatorEx -
Структура, используемая для описания механизма выделения блоков памяти. Структура содержит следующие поля:
Поле
Значение
void *ctxконтекст пользователя, передаваемый в качестве первого аргумента
void* malloc(void *ctx, size_t size)выделить блок памяти
void* calloc(void *ctx, size_t nelem, size_t elsize)выделить блок памяти, инициализированный нулями
void* realloc(void *ctx, void *ptr, size_t new_size)выделить или изменить размер блока памяти
void free(void *ctx, void *ptr)освободить блок памяти
Изменено в версии 3.5: Структура
PyMemAllocatorбыла переименована вPyMemAllocatorEx, и добавлено новое полеcalloc.
-
type PyMemAllocatorDomain -
Перечисление, используемое для идентификации области выделения. Области:
-
PYMEM_DOMAIN_RAW -
Функции:
-
PYMEM_DOMAIN_MEM -
Функции:
-
PYMEM_DOMAIN_OBJ -
Функции:
-
-
void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator) -
Получить механизм выделения блоков памяти указанной области.
-
void PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator) -
Установить механизм выделения блоков памяти указанной области.
Новый механизм должен возвращать distinct не-
NULLуказатель при запросе нулевого количества байтов.Для области
PYMEM_DOMAIN_RAW, механизм должен быть потокобезопасным: блокировка глобального интерпретатора (GIL) не должна быть взята при вызове механизма.Для остальных областей механизм также должен быть потокобезопасным: к механизму может быть обращение в различных интерпретаторах, не использующих общий
GIL.Если новый механизм не является хэндлером (не вызывает предыдущий механизм), функция
PyMem_SetupDebugHooks()должна быть вызвана для переустановки отладочных хэндлеров поверх нового механизма.См. также
PyPreConfig.allocatorи Предварительная инициализация Python с PyPreConfig.Предупреждение
PyMem_SetAllocator()имеет следующие условия:- Он может быть вызван после
Py_PreInitialize()и доPy_InitializeFromConfig()для установки пользовательского механизма выделения памяти. Нет ограничений на установленный механизм, кроме тех, которые накладывает область (например, область Raw позволяет механизму быть вызванной без блокировки GIL). Подробнее см. раздел о областях механизма выделения памяти. - Если вызван после завершения инициализации Python (после вызова
Py_InitializeFromConfig()), механизм обязан оборачивать существующий механизм. Замена текущего механизма другим произвольным не поддерживается.
Изменено в версии 3.12: Все механизмы должны быть потокобезопасными.
- Он может быть вызван после
-
void PyMem_SetupDebugHooks(void) -
Настроить отладочные хэндлеры в механизмах выделения памяти Python для обнаружения ошибок памяти.
Отладочные крючки для выделения памяти Python
Когда Python скомпилирован в отладочном режиме, функция PyMem_SetupDebugHooks() вызывается во время предварительной инициализации Python (предварительная инициализация Python) для настройки отладочных крючков на выделения памяти Python, чтобы обнаруживать ошибки памяти.
Переменная среды PYTHONMALLOC может быть использована для установки отладочных крючков для Python, скомпилированного в релизном режиме (например: PYTHONMALLOC=debug).
Функция PyMem_SetupDebugHooks() может быть использована для установки отладочных крючков после вызова PyMem_SetAllocator().
Эти отладочные крючки заполняют динамически выделенные блоки памяти специальными, распознаваемыми битовыми шаблонами. Недавно выделенная память заполняется байтом 0xCD (PYMEM_CLEANBYTE), освобождённая память заполняется байтом 0xDD (PYMEM_DEADBYTE). Блоки памяти окружены «запрещенными байтами», заполненными байтом 0xFD (PYMEM_FORBIDDENBYTE). Последовательности этих байтов вряд ли будут являться допустимыми адресами, числами с плавающей точкой или строками ASCII.
Проверки во время выполнения:
- Обнаружение нарушений API. Например, обнаружение вызова
PyObject_Free()для блока памяти, выделенного с помощьюPyMem_Malloc(). - Обнаружение записи перед началом буфера (подпоток буфера).
- Обнаружение записи после конца буфера (переполнение буфера).
- Проверка, что блокировка интерпретатора (GIL) удерживается при вызове функций выделения памяти в области
PYMEM_DOMAIN_OBJ(например:PyObject_Malloc()) иPYMEM_DOMAIN_MEM(например:PyMem_Malloc()).
При ошибке отладочные крючки используют модуль tracemalloc для получения трассировки, где был выделен блок памяти. Трассировка отображается только в том случае, если tracemalloc отслеживает выделение памяти Python и блок памяти был прослежен.
Пусть S = sizeof(size_t). К каждому концу каждого блока из N байт добавляется 2*S байт. Размещение памяти выглядит следующим образом, где p представляет адрес, возвращаемый функцией malloc-подобного или realloc-подобного типа (p[i:j] означает срез байтов с *(p+i) включительно до *(p+j) не включая; обратите внимание, что обработка отрицательных индексов отличается от срезов Python):
-
p[-2*S:-S] -
Количество байт, изначально запрошенных для выделения. Это значение типа size_t, хранящееся в формате big-endian (легче для чтения в дампе памяти).
-
p[-S] -
Идентификатор API (символ ASCII):
-
'r'дляPYMEM_DOMAIN_RAW. -
'm'дляPYMEM_DOMAIN_MEM. -
'o'дляPYMEM_DOMAIN_OBJ.
-
-
p[-S+1:0] -
Копии PYMEM_FORBIDDENBYTE. Используются для отслеживания подзаписи и чтения.
-
p[0:N] -
Запрошенная память, заполненная копиями PYMEM_CLEANBYTE, используется для отслеживания ссылок на неинициализированную память. Когда вызывается функция realloc-подобного типа, запрашивающая больший блок памяти, новые дополнительные байты также заполняются PYMEM_CLEANBYTE. Когда вызывается функция free-подобного типа, эти байты перезаписываются PYMEM_DEADBYTE, чтобы отследить ссылки на освобождённую память. Когда вызывается функция realloc-подобного типа, запрашивающая меньший блок памяти, избыточные старые байты также заполняются PYMEM_DEADBYTE.
-
p[N:N+S] -
Копии PYMEM_FORBIDDENBYTE. Используются для отслеживания перезаписи и чтения.
-
p[N+S:N+2*S] -
Используется только в том случае, если определена макрос
PYMEM_DEBUG_SERIALNO. (По умолчанию не определено).Порядковый номер, увеличивающийся на 1 при каждом вызове функции malloc-подобного или realloc-подобного типа. В формате big-endian
size_t. Если позже обнаруживается «плохая память», порядковый номер предоставляет отличный способ установить точку останова на следующей загрузке, чтобы зафиксировать момент, когда этот блок был выдан. Статическая функция bumpserialno() в obmalloc.c — единственное место, где увеличивается порядковый номер, и она существует, чтобы вы могли легко установить такую точку останова.
Функция realloc-подобного или free-подобного типа сначала проверяет, что байты PYMEM_FORBIDDENBYTE на каждом конце блока не изменены. Если они были изменены, диагностическое сообщение выводится в stderr, и выполнение программы прерывается с помощью Py_FatalError(). Другая основная проблема — вызывать ошибку памяти, когда программа считывает один из специальных шаблонов битов и пытается использовать его как адрес. Если вы окажетесь в отладчике в этот момент и посмотрите на объект, вы, скорее всего, увидите, что он полностью заполнен PYMEM_DEADBYTE (что означает, что используется освобождённая память) или PYMEM_CLEANBYTE (что означает, что используется неинициализированная память).
Изменено в версии 3.6: Функция PyMem_SetupDebugHooks() теперь также работает с Python, скомпилированным в релизном режиме. При ошибке отладочные крючки теперь используют tracemalloc для получения трассировки, где был выделен блок памяти. Отладочные крючки теперь также проверяют, удерживается ли блокировка интерпретатора (GIL), когда вызываются функции областей PYMEM_DOMAIN_OBJ и PYMEM_DOMAIN_MEM.
Изменено в версии 3.8: Шаблоны байтов 0xCB (PYMEM_CLEANBYTE), 0xDB (PYMEM_DEADBYTE) и 0xFB (PYMEM_FORBIDDENBYTE) были заменены на 0xCD, 0xDD и 0xFD для использования тех же значений, что и в отладочных крючках CRT Windows malloc() и free().
Алгоритм выделения памяти pymalloc
Python имеет алгоритм выделения памяти pymalloc, оптимизированный для небольших объектов (не более 512 байт) с коротким сроком жизни. Он использует карты памяти, называемые «аренами», с фиксированным размером 256 Кбайт на 32-битных платформах или 1 Мбайт на 64-битных платформах. Для выделений больше 512 байт он обращается к PyMem_RawMalloc() и PyMem_RawRealloc().
pymalloc является по умолчанию для области PYMEM_DOMAIN_MEM (например, PyMem_Malloc()) и области PYMEM_DOMAIN_OBJ (например, PyObject_Malloc()).
Алгоритм выделения памяти в аренах использует следующие функции:
-
VirtualAlloc()иVirtualFree()в Windows, -
mmap()иmunmap()если доступны, -
malloc()иfree()в противном случае.
Этот алгоритм отключен, если Python сконфигурирован с опцией --without-pymalloc. Его также можно отключить во время выполнения, используя переменную среды PYTHONMALLOC (например: PYTHONMALLOC=malloc).
Настройка алгоритма выделения памяти pymalloc Arena
Добавлен в версии 3.4.
-
type PyObjectArenaAllocator -
Структура, описывающая алгоритм выделения памяти в аренах. Структура имеет три поля:
Поле
Значение
void *ctxконтекст пользователя, переданный в качестве первого аргумента
void* alloc(void *ctx, size_t size)выделяет арену размером bytes
void free(void *ctx, void *ptr, size_t size)освобождает арену
-
void PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator) -
Возвращает алгоритм выделения памяти в аренах.
-
void PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator) -
Устанавливает алгоритм выделения памяти в аренах.
Алгоритм выделения памяти mimalloc
Добавлен в версии 3.13.
Python поддерживает алгоритм выделения памяти mimalloc, когда поддерживается платформа. mimalloc «является универсальным алгоритмом выделения памяти с отличными характеристиками производительности. Первоначально разработан Даном Лейеном для систем выполнения языков Koka и Lean».
API C tracemalloc
Добавлена в версии 3.7.
-
int PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, size_t size) -
Отслеживание блока выделенной памяти в модуле
tracemalloc.Возвращает
0при успехе,-1при ошибке (не удалось выделить память для хранения трассировки). Возвращает-2если tracemalloc отключен.Если блок памяти уже отслеживается, обновляется существующая трассировка.
-
int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr) -
Отслеживание блока выделенной памяти в модуле
tracemalloc. Ничего не делает, если блок не отслеживался.Возвращает
-2если tracemalloc отключен, в противном случае возвращает0.
Примеры
Вот пример из раздела Обзор, переписанный так, что буфер ввода-вывода выделяется из кучи Python с использованием первого набора функций:
PyObject *res;
char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */
if (buf == NULL)
return PyErr_NoMemory();
/* ...Do some I/O operation involving buf... */
res = PyBytes_FromString(buf);
PyMem_Free(buf); /* allocated with PyMem_Malloc */
return res;
Тот же код, использующий набор функций, ориентированных на тип:
PyObject *res;
char *buf = PyMem_New(char, BUFSIZ); /* for I/O */
if (buf == NULL)
return PyErr_NoMemory();
/* ...Do some I/O operation involving buf... */
res = PyBytes_FromString(buf);
PyMem_Del(buf); /* allocated with PyMem_New */
return res;
Обратите внимание, что в обоих примерах выше буфер всегда обрабатывается с помощью функций из одного и того же набора. Действительно, необходимо использовать одну и ту же семейство API памяти для данного блока памяти, чтобы свести к минимуму риск смешивания разных аллокаторов. Следующая последовательность кода содержит две ошибки, одна из которых помечена как критическая, так как она смешивает два разных аллокатора, работающих с разными кучами.
char *buf1 = PyMem_New(char, BUFSIZ); char *buf2 = (char *) malloc(BUFSIZ); char *buf3 = (char *) PyMem_Malloc(BUFSIZ); ... PyMem_Del(buf3); /* Wrong -- should be PyMem_Free() */ free(buf2); /* Right -- allocated via malloc() */ free(buf1); /* Fatal -- should be PyMem_Del() */
Помимо функций, предназначенных для обработки блоков сырой памяти из кучи Python, объекты в Python выделяются и освобождаются с помощью PyObject_New, PyObject_NewVar и PyObject_Del().
Они будут объяснены в следующей главе о определении и реализации новых типов объектов на C.
© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/c-api/memory.html