Динамическое выделение памяти: пулы памяти для эффективного управления в реальном времени. Альтернатива malloc/new, избегающая фрагментации и повышающая производительность.
Сравнивайте с английским: нажмите на абзац — оригинал откроется в окне. Кнопка EN под абзацем показывает его прямо в тексте.
Введение
Метод динамического выделения памяти
Dynamic memory allocation method
Пулы памяти, также называемые выделением блоков фиксированного размера, – это использование пулов для управления памятью, позволяющее динамически выделять память. Динамическое выделение памяти можно реализовать с помощью таких методов, как malloc и оператор new в C++; хотя это устоявшиеся и надежные реализации, они подвержены фрагментации из-за переменных размеров блоков, поэтому их не рекомендуется использовать в системах реального времени из-за проблем с производительностью. Более эффективным решением является предварительное выделение нескольких блоков памяти одинакового размера, образующих пул памяти. Приложение может выделять, обращаться и освобождать блоки, представленные дескрипторами во время выполнения. Многие операционные системы реального времени используют пулы памяти, например, Transaction Processing Facility. Некоторые системы, такие как веб-сервер Nginx, используют термин "пул памяти" для обозначения группы выделений переменного размера, которые можно освободить сразу. Это также известно как область; см. управление памятью, основанное на областях.
Memory pools, also called fixed size blocks allocation, is the use of pools for memory management that allows dynamic memory allocation. Dynamic memory allocation can, and has been achieved through the use of techniques such as malloc and C++'s operator new; although established and reliable implementations, these suffer from fragmentation because of variable block sizes, it is not recommendable to use them in a real time system due to performance. A more efficient solution is preallocating a number of memory blocks with the same size called the memory pool. The application can allocate, access, and free blocks represented by handles at run time. Many real time operating systems use memory pools, such as the Transaction Processing Facility. Some systems, like the web server Nginx, use the term memory pool to refer to a group of variable size allocations which can be later deallocated all at once. This is also known as a region; see region based memory management.
Простая реализация пула памяти
Простой модуль пула памяти может выделять, например, три пула во время компиляции с размерами блоков, оптимизированными для приложения, использующего этот модуль. Приложение может выделять, получать доступ и освобождать память через следующий интерфейс:
A simple memory pool module can allocate, for example, three pools at compile time with block sizes optimized for the application deploying the module. The application can allocate, access and free memory through the following interface:
Выделение памяти из пулов. Функция определяет пул, в котором помещается требуемый блок. Если все блоки в этом пуле уже зарезервированы, функция пытается найти блок в следующем пуле большего размера (или в последующих пулах большего размера). Выделенный блок памяти представлен дескриптором. Получение указателя доступа к выделенной памяти. Освобождение ранее выделенного блока памяти. Дескриптор, например, может быть реализован как целое число без знака. Модуль может интерпретировать дескриптор внутренне, разделяя его на индекс пула, индекс блока памяти и номер версии. Индекс пула и блока памяти обеспечивают быстрый доступ к соответствующему блоку по дескриптору, а номер версии, который увеличивается при каждом новом выделении, позволяет обнаруживать дескрипторы, чей блок памяти уже освобожден (из-за слишком долгого хранения дескриптора).
Allocate memory from the pools. The function will determine the pool where the required block fits in. If all blocks of that pool are already reserved, the function tries to find one in the next bigger pool(s). An allocated memory block is represented with a handle. Get an access pointer to the allocated memory. Free the formerly allocated memory block. The handle can for example be implemented with an unsigned int. The module can interpret the handle internally by dividing it into pool index, memory block index and a version. The pool and memory block index allow fast access to the corresponding block with the handle, while the version, which is incremented at each new allocation, allows detection of handles whose memory block is already freed (caused by handles retained too long).