-
Notifications
You must be signed in to change notification settings - Fork 43
[8pt] Describe LuaJIT memory profiler interface and parser #1753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Some of FAQ: Q: Why is there so much Q: Why there is some reallocations/deallocations without Q: Why some objects are not collected during profiler recording? Is it a memory leak? Q: Can I profile not a current chunk, but the whole running application? Can I start profiler when the application is already running? local fiber = require "fiber"
local log = require "log"
fiber.create(function()
fiber.name("memprof")
collectgarbage() -- Collect all already dead objects.
log.warn("start of profile")
local st, err = misc.memprof.start(FILENAME)
if not st then
log.error("failed to start profiler: %s", err)
end
fiber.sleep(TIME)
collectgarbage()
st, err = misc.memprof.stop()
if not st then
log.error("profiler on stop error: %s", err)
end
log.warn("end of profile")
end) Where |
The example of investigation of the memory profiler's report. Assume we have the following Lua code named <format_concat.lua>: 1 jit.off() -- More verbose reports.
2
3 local function concat(a)
4 local nstr = a.."a"
5 return nstr
6 end
7
8 local function format(a)
9 local nstr = string.format("%sa", a)
10 return nstr
11 end
12
13 collectgarbage() -- Clean up.
14
15 local binfile = "/tmp/memprof_"..(arg[0]):match("([^/]*).lua")..".bin"
16
17 local st, err = misc.memprof.start(binfile)
18 assert(st, err)
19
20 -- Payload.
21 for i = 1, 10000 do
22 local f = format(i)
23 local c = concat(i)
24 end
25 collectgarbage() -- Clean up.
26
27 local st, err = misc.memprof.stop()
28 assert(st, err)
29
30 os.exit() If one runs this code via Tarantool and parses the memory profiler's report he sees the following output:
The reasonable questions are: First things first. But why there are so many allocations? Almost double of the expected amount. This is because OK, let's comment the 22nd line (by adding The profiler's report is the following:
Q: But what will change if we enable JIT compilation?
This is because after 56 iterations trace is compiled and JIT-compiler removed unused variable Lets now to profile only
Q: Why there is so many allocation against If we change the 8 local function format(a)
9 local nstr = string.format("%sa", tostring(a))
10 return nstr
11 end the results become much prettier:
|
The most common case: I have an Tarantool that fails due to Lua OOM (for example, "normal" memory consumption is slightly lower than 1Gb, and load spikes quickly lead to OOM). I want to know how ate all the memory - what should I do now?
@Buristan these are questions for you, I assume |
@sharonovd
NB: taking into account that this profiling takes place with JIT enabled, many allocations will be reported as Regarding OOM error -- Mike solves (if tests will not show the opposite) this problem for all architectures except 32-bit ARM and Windows on x86, so it looks like the user should update Tarantool to version with exceptions on traces support. I hope that this patch will be backported in 2.9.1. |
Introduce a new document on LuaJIT memory profiler * LuaJIT memory profiler is a new feature implemented in Tarantool 2.7.1. The document describes the profiler's behavior as of this Tarantool version. * The document is placed in the Application server chapter. Closes #1753
LuaJIT memory profiler interface and parser
Product: Tarantool
Since: 2.7.1
Audience/target: developers, operations: what's making my Tarantool slow
Root document: where to add or update documentation
SME: @igormunkin @Buristan
Peer reviewer: @
Details
Tarantool 2.7.1 release introduced the LuaJIT memory profiler (gh-5442) and the profile parser (gh-5490).
This version of LuaJIT memory profiler does not support verbose reporting allocations from traces. All allocation from traces are reported as internal. But trace code semantics should be totally the same as for the Lua interpreter (excluding sink optimizations). Also all deallocations reported as internal too.
Tail call optimization does not create a new call frame, so all allocations inside the function called via
CALLT
/CALLMT
bytecodes are attributed to its caller.Usually developers are not interested in information about allocations inside builtins. So if builtin function was called from a Lua function all allocations are attributed to this Lua function. Otherwise attribute this event to a C function.
Assume we have the following Lua chunk named <test.lua>:
Binary data can be read via Tarantool itself via the following command (NB: mind the dash prior to the dump filename):
$ tarantool -e 'require("memprof")(arg[1])' - memprof_new.bin
It parses the binary format provided by memory profiler and render it on human-readable format.
If one run the chunk above the profiler reports approximately the following:
Plain text of profiled info has the following format:
INTERNAL
means that these allocations are caused by internal LuaJIT structures. Note that events are sorted from the most often to the least.Overrides
means what allocation this reallocation overrides.Starting profiler from Lua is quite simple:
where
fname
is name of the file where profile events are written. Writer for this function performfwrite()
for each call retrying in case ofEINTR
. When the profiling is stopped thefclose()
is called. If it is impossible to open a file for writing or profiler fails to start, returnsnil
on failure (plus an error message as a second result and a system-dependent error code as a third result). Otherwise returnstrue
value.Stopping profiler from Lua is simple too:
If there is any error occurred at profiling stopping (an error when file descriptor was closed) or during reporting
memprof.stop()
returnsnil
(plus an error message as a second result and a system-dependent error code as a third result). Returnstrue
otherwise.Also, see some possible FAQs in the issue comments
@veod32
Possibly, we can firstly create a short MVP document that can be enough for our developers to have a try. Then publish it and collect developers' feedback on the functionality.
The text was updated successfully, but these errors were encountered: