tarantool / doc

Tarantool documentation
https://www.tarantool.io/en/doc/
Other
14 stars 43 forks source link

Document the LuaJIT platform profiler #2587

Open veod32 opened 2 years ago

veod32 commented 2 years ago

Product: Tarantool Since: 2.10 Root document: TBD (a new section/page for a new document) Dev issue: https://github.com/tarantool/tarantool/issues/4001 , https://github.com/tarantool/tarantool/issues/781 SME: @ igormunkin , @ fckxorg

Details

TBD

mkokryashkin commented 2 years ago

Sysprof

The default profiling options for LuaJIT are not fine enough to get an understanding of performance. For example, perf only able to show host stack, so all the Lua calls are seen as single pcall. Oppositely, the jit.p module provided with LuaJIT is not able to give any information about the host stack. Here comes the sysprof: it is able to capture both guest and host stacks simultaneously, along with virtual machine states.

The C API

Configuration:

All of the functions return 0 on success and an error code on failure.

The configuration types are:

/* Profiler configurations. */
/*
** Writer function for profile events. Must be async-safe, see also
** `man 7 signal-safety`.
** Should return amount of written bytes on success or zero in case of error.
** Setting *data to NULL means end of profiling.
** For details see <lj_wbuf.h>.
*/
typedef size_t (*sp_writer)(const void **data, size_t len, void *ctx);
/*
** Callback on profiler stopping. Required for correctly cleaning
** at VM finalization when profiler is still running.
** Returns zero on success.
*/
typedef int (*sp_on_stop)(void *ctx, uint8_t *buf);
/*
** Backtracing function for the host stack. Should call `frame_writer` on
** each frame in the stack in the order from the stack top to the stack
** bottom. The `frame_writer` function is implemented inside the sysprof
** and will be passed to the `backtracer` function. If `frame_writer` returns
** NULL, backtracing should be stopped. If `frame_writer` returns not NULL,
** the backtracing should be continued if there are frames left.
*/
typedef void (*sp_backtracer)(void *(*frame_writer)(int frame_no, void *addr));

Profiler options are the following:

struct luam_Sysprof_Options {
  /* Profiling mode. */
  uint8_t mode;
  /* Sampling interval in msec. */
  uint64_t interval;
  /* Custom buffer to write data. */
  uint8_t *buf;
  /* The buffer's size. */
  size_t len;
  /* Context for the profile writer and final callback. */
  void *ctx;
};

Profiling modes:

/*
** DEFAULT mode collects only data for luam_sysprof_counters, which is stored
** in memory and can be collected with luaM_sysprof_report after profiler
** stops.
*/
#define LUAM_SYSPROF_DEFAULT 0
/*
** LEAF mode = DEFAULT + streams samples with only top frames of host and
** guests stacks in format described in <lj_sysprof.h>
*/
#define LUAM_SYSPROF_LEAF 1
/*
** CALLGRAPH mode = DEFAULT + streams samples with full callchains of host
** and guest stacks in format described in <lj_sysprof.h>
*/
#define LUAM_SYSPROF_CALLGRAPH 2

Counters structure for the luaM_Sysprof_Report:

struct luam_Sysprof_Counters {
  uint64_t vmst_interp;
  uint64_t vmst_lfunc;
  uint64_t vmst_ffunc;
  uint64_t vmst_cfunc;
  uint64_t vmst_gc;
  uint64_t vmst_exit;
  uint64_t vmst_record;
  uint64_t vmst_opt;
  uint64_t vmst_asm;
  uint64_t vmst_trace;
  /*
  ** XXX: Order of vmst counters is important: it should be the same as the
  ** order of the vmstates.
  */
  uint64_t samples;
};

Caveats:

The Lua API

First two functions return boolean res and err, which is nil on success and contains an error message on failure

misc.sysprof.report returns a lua table containing the following counters:

{
  "samples" = int,
  "INTERP" = int,
  "LFUNC" = int,
  "FFUNC" = int,
  "CFUNC" = int,
  "GC" = int,
  "EXIT" = int,
  "RECORD" = int,
  "OPT" = int,
  "ASM" = int,
  "TRACE" = int
}

Parameter opts for the misc.sysprof.start can contain the following parameters:

{
  mode = 'D'/'L'/'C', -- 'D' = DEFAULT, 'L' = LEAF, 'C' = CALLGRAPH
  interval = 10, -- sampling interval in msec.
  path = '/path/to/file' -- location to store profile data.
}

Mode MUST be provided always, interval and path are optional. The default interval is 10 msec, path -- sysprof.bin

Parsers

The default profile data parser is provided. Its output is flamegraph.pl-suitable, so one can do this:

$ luajit-parse-sysprof /path/to/profile/data > tmp
$ flamegraph.pl tmp > graph.svg
a1div0 commented 1 year ago

Пример использования

  1. Подключаемся к экземпляру
  2. Запускаем трассировку:
    misc.sysprof.start({
        mode = 'C', -- 'D' = DEFAULT, 'L' = LEAF, 'C' = CALLGRAPH
        interval = 10, -- sampling interval in msec.
        path = '/path/to/save/file.bin' -- location to store profile data.
    })

    Вывод:

    ---
    - true
    ...
  3. Останавливаем трассировку:

    misc.sysprof.stop()

    Вывод:

    ---
    - true
    ...
  4. Выходим из экземпляра и выполняем:
    tarantool -e 'require("sysprof")(arg[1])' - /path/to/save/file.bin > /path/to/save/out.bin
    ./flamegraph.pl /path/to/save/out.bin > /path/to/save/out.svg

    flamegraph.pl

  5. Смотрим SVG