Поиск утечек памяти в Lua
Перенос информации с /docs
Пришлось столкнуться. Мои микрозаметки на этот счет.
Все, что описано ниже может быть полезным, но в моем случае полезнее всего оказалось сбилдить LuaJit от Tarantool и использовать встроенный в него memory profiler (memprof), который покажет где и сколько памяти не высвободилось в коде.
Ручной поиск
В таймере каждую секунду принтить collectgarbage("count") / 1024
, удаляя подозреваемые куски кода, пока память не перестанет "улетать в трубу". Такой себе способ.
-- Заметка для личного пользования
timer.Create("gc_count", 1, 0, function()
local freeMem = collectgarbage("count")
print("GC Count: " .. math.Round(freeMem / 1024, 2) .. " MB")
end)
Для таймера и Round используется библиотека lua-gmod-lib
Инструменты
Может быть интересно полистать: мини презентация по разным инструментам для поиска утечек
Я использую LuaMemorySnapshotDump + lua-microscope
в связке.
LuaMemorySnapshotDump
LuaMemorySnapshotDump - делает файлы с дампом памяти. Чистый lua без сторонних модулей. Нужно сделать снимок "до" и "после" того, как часть памяти "уплыла", затем через этот же тул сделать diff
local mri = require("MemoryReferenceInfo")
mri.m_cConfig.m_bAllMemoryRefFileAddTime = false
print("dump BEFORE")
collectgarbage("collect")
mri.m_cMethods.DumpMemorySnapshot("./", "1-Before", -1)
print("waiting some time before next dump")
timer.Simple(120, function()
print("dump AFTER")
collectgarbage("collect")
mri.m_cMethods.DumpMemorySnapshot("./", "2-After", -1)
print("dump COMPARED")
mri.m_cMethods.DumpMemorySnapshotComparedFile("./", "Compared", -1, "./LuaMemRefInfo-All-[1-Before].txt", "./LuaMemRefInfo-All-[2-After].txt")
print("DONE BLYAT!!")
end)
В репе есть example файл и очень понятное readme. Конечный файл нужно выглядывать глазками. Выглядит примерно так:
--------------------------------------------------------
-- This is compared memory information.
--------------------------------------------------------
-- Collect base memory reference at line:-1@file:./LuaMemRefInfo-All-[1-Before].txt
-- Collect compared memory reference at line:-1@file:./LuaMemRefInfo-All-[2-After].txt
--------------------------------------------------------
-- [Table/Function/String Address/Name] [Reference Path] [Reference Count]
--------------------------------------------------------
string: "China" registry.2[_G].Author.Country[string] 1
function: 0x5618d4a99f10 registry.2[_G].Author.Ask[line:33@file:Example.lua] 1
string: "Beijing" registry.2[_G].Author.City[string] 1
string: "Game Developer" registry.2[_G].Author.Job[string] 1
string: "Game, Travel, Gym" registry.2[_G].Author.Hobby[string] 1
string: "yaukeywang" registry.2[_G].Author.Name[string] 1
table: 0x5618d4a7e5f0 registry.2[_G].Author 1
lua-microscope
lua-microscope – собирает информацию об указанной таблице, на выходе дает файл, который можно скормить GraphViz и получить КАРТИНКУ памяти
Быстрый тест:
git clone git@github.com:siffiejoe/lua-microscope.git
cd lua-microscope
$ cat > test.lua
local up1 = false
local up2 = io.stdout
local t1 = { val = 1 }
local t2 = { val = 2 }
setmetatable( t1, { __index = function( t, k )
if t2[ k ] ~= nil then
return t2[ k ]
else
return up1 or up2
end
end } )
setmetatable( t2, { __index = t1 } )
require( "microscope" )( "example1.dot", t1 )
lua test.lua
# http://www.graphviz.org/download/
dot -T jpeg -o example1.jpeg example1.dot
loom
У luajit есть модуль dump, запускается примерно так: luajit -jdump=T -e 'local s = 0; for i = 1, 100 do s = s + i end; print(s)'
. Он генерирует .txt или .html файлик с информацией о "трассах памяти"(?). Короче, вот такие отчеты: клик.
На основе этих отчетов можно построить визуализации о работе jit компилятора.
Loom от CloudFlare улучшает эти отчеты, генерируя более подробный и красивый html файлик. Пальцем наугад я заметил в этих отчетах хоть только один, но очень важный участок кода, который поправил. Уверен, можно и больше, но пока что мне не хватает опыта.
Установка проста: git clone
, mv jit $путь_в_пределах_package.path
, mv loom.html $папка_с_initlua
. Потом запускаем свой скрипт: luajit -jloom=loom.html,loom_dump.html init.lua