Как современные VMs обрабатывают выделение памяти?
Я работаю над простой машиной стека, написанной на C, в основном для учебных целей. После использования malloc/free
для моих операций с памятью я подумал, что было бы неплохо прочитать определенный код выделения памяти из современных виртуальных машин.
Я загрузил исходный код Lua и начал его читать. Через некоторое время я понял, что есть много макросов, и я не мог найти код, в котором выполняется реальное распределение памяти (т. е. malloc
призывать.)
find . -exec grep -i "malloc" '{}' ; -print
он напечатал только некоторые макросы Lua, которые имеют malloc
слово в своих названиях. Lua VM (и язык программирования) не использует malloc
на всех!
Итак, это приводит меня к вопросу: как современные VMs обрабатывают выделение памяти? Как Lua выделяет память из кучи? Есть ли какие-либо способы выделения, кроме malloc
? Какие плюсы/минусы других методов?
мне также интересно о лучших практиках, шаблонах дизайна и т. д. для безопасного работа над выделенной памятью. Я вижу в источнике Lua, что перед выделением памяти существует много косвенных действий. Где я могу узнать об этом?
2 ответов
Lua определенно использует malloc
, в виде realloc
(можно также передать пользовательский распределитель), однако, поскольку Lua использует GC как 99% языков на основе VM, он использует макросы для автоматического добавления блока заголовка GC к распределению.
вы найдете память Луа все обрабатывается LuaM_
подпрограммы lmem.c
и lmem.h
, все они используют глобальное состояние виртуальной машины для хранения распределителя, который изначально установлен в l_alloc
(от lauxlib.c
), но может быть изменен by lua_setallocf
.
недавно LuaJIT добавил выделение тонет и планирует некоторые действительно интересные функции памяти, которые вы можете прочитать в этой статье на LuaJIT Сбор Мусора. В статье рассматривается много стратегии и дизайна, вращающихся вокруг выделения памяти VM/JIT, погружения, агрегации и сбора мусора.
как вы можете видеть, стратегии выделения памяти и потопления очень тесно связаны с GC, который использует (если таковые имеются).
In термины pro и con различной памяти распределители, используя стандартный malloc
прост в использовании, но за счет скорости и потерь на выравнивание и различных дополнительных блоков, помеченных на каждом распределении.
переход к более продвинутым распределителям arena, pool, slab и block, мы можем значительно ускорить процесс (особенно для внутренних распределений VM фиксированного размера) и избежать фрагментации и накладных расходов, которые могут возникнуть с более общими распределителями, такими как malloc
, но, конечно, эти распределители более сложны, и вы должны отлаживать их, если вы начинаете с нуля (что в большей системе, такой как виртуальная машина, просто просит проблем), как и в проверенной CRT malloc
реализация.
ядро Lua не использует malloc
и друзей. Он полагается на пользовательскую функцию выделения памяти, которая имеет realloc
семантику (а точне при лечении NULL
указатели и размеры 0). См.lua_Alloc.
вспомогательная библиотека Lua обеспечивает удобство luaL_newstate
функция, которая создает состояние Lua через core