From: Sergey Bronnikov via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: Maxim Kokryashkin <max.kokryashkin@gmail.com>,
tarantool-patches@dev.tarantool.org, skaplun@tarantool.org
Subject: Re: [Tarantool-patches] [PATCH luajit v2 5/6] memprof: introduce the `--human-readable` option
Date: Wed, 20 Dec 2023 15:24:15 +0300 [thread overview]
Message-ID: <ef8ed77b-5cc2-4816-af0c-95c84905a579@tarantool.org> (raw)
In-Reply-To: <1db6ff8c7469b5f59d1ee13b824bc223b02883a2.1701888856.git.m.kokryashkin@tarantool.org>
Thanks for the patch!
LGTM
On 12/6/23 21:55, Maxim Kokryashkin wrote:
> Prior to this patch, memprof could report only the raw
> amount of bytes, which is hard to read. This patch adds the
> `--human-readable` CLI option to the memprof parser, so the
> memory is reported in KiB, MiB, or GiB, depending on what's
> the biggest reasonable unit.
>
> This patch also refactors the options mechanism for parser,
> so all of the options are passed into parser's modules as a
> single config table instead of being handled individually.
>
> Part of tarantool/tarantool#5994
> ---
> .../gh-5994-memprof-human-readable.test.lua | 73 +++++++++++++++++++
> tools/memprof.lua | 20 +++--
> tools/memprof/humanize.lua | 46 +++++++++---
> 3 files changed, 123 insertions(+), 16 deletions(-)
> create mode 100644 test/tarantool-tests/gh-5994-memprof-human-readable.test.lua
>
> diff --git a/test/tarantool-tests/gh-5994-memprof-human-readable.test.lua b/test/tarantool-tests/gh-5994-memprof-human-readable.test.lua
> new file mode 100644
> index 00000000..e34291be
> --- /dev/null
> +++ b/test/tarantool-tests/gh-5994-memprof-human-readable.test.lua
> @@ -0,0 +1,73 @@
> +local tap = require('tap')
> +local test = tap.test('gh-5994-memprof-human-readable'):skipcond({
> + ['Profile tools are implemented for x86_64 only'] = jit.arch ~= 'x86' and
> + jit.arch ~= 'x64',
> + ['Profile tools are implemented for Linux only'] = jit.os ~= 'Linux',
> + -- XXX: Tarantool integration is required to run this test properly.
> + -- luacheck: no global
> + ['No profile tools CLI option integration'] = _TARANTOOL,
> +})
> +
> +local utils = require('utils')
> +local TMP_BINFILE_MEMPROF = utils.tools.profilename('memprofdata.tmp.bin')
> +local PARSE_CMD = utils.exec.luacmd(arg) .. ' -tm '
> +
> +local function generate_output(bytes)
> + local res, err = misc.memprof.start(TMP_BINFILE_MEMPROF)
> + -- Should start successfully.
> + assert(res, err)
> +
> + -- luacheck: no unused
> + local _ = string.rep('_', bytes)
> +
> + res, err = misc.memprof.stop()
> + -- Should stop successfully.
> + assert(res, err)
> +end
> +
> +local TEST_SET = {
> + {
> + bytes = 2049,
> + match = '%dB',
> + hr = false,
> + name = 'non-human-readable mode is correct'
> + },
> + {
> + bytes = 100,
> + match = '%dB',
> + hr = true,
> + name = 'human-readable mode: bytes'
> + },
> + {
> + bytes = 2560,
> + match = '%d+%.%d%dKiB',
> + hr = true,
> + name = 'human-readable mode: float'
> + },
> + {
> + bytes = 2048,
> + match = '%dKiB',
> + hr = true,
> + name = 'human-readable mode: KiB'
> + },
> + {
> + bytes = 1024 * 1024,
> + match = '%dMiB',
> + hr = true,
> + name = 'human-readable mode: MiB'
> + },
> + -- XXX: The test case for GiB is not implemented because it is
> + -- OOM-prone for non-GC64 builds.
> +}
> +
> +test:plan(#TEST_SET)
> +
> +for _, params in ipairs(TEST_SET) do
> + generate_output(params.bytes)
> + local cmd = PARSE_CMD .. (params.hr and ' --human-readable ' or '')
> + local output = io.popen(cmd .. TMP_BINFILE_MEMPROF):read('*all')
> + test:like(output, params.match, params.name)
> +end
> +
> +os.remove(TMP_BINFILE_MEMPROF)
> +test:done(true)
> diff --git a/tools/memprof.lua b/tools/memprof.lua
> index 955a1327..537cb869 100644
> --- a/tools/memprof.lua
> +++ b/tools/memprof.lua
> @@ -22,6 +22,12 @@ local match, gmatch = string.match, string.gmatch
> -- Program options.
> local opt_map = {}
>
> +-- Default config for the memprof parser.
> +local config = {
> + leak_only = false,
> + human_readable = false,
> +}
> +
> function opt_map.help()
> stdout:write [[
> luajit-parse-memprof - parser of the memory usage profile collected
> @@ -34,14 +40,18 @@ luajit-parse-memprof [options] memprof.bin
> Supported options are:
>
> --help Show this help and exit
> + --human-readable Use KiB/MiB/GiB notation instead of bytes
> --leak-only Report only leaks information
> ]]
> os.exit(0)
> end
>
> -local leak_only = false
> opt_map["leak-only"] = function()
> - leak_only = true
> + config.leak_only = true
> +end
> +
> +opt_map["human-readable"] = function()
> + config.human_readable = true
> end
>
> -- Print error and exit with error status.
> @@ -101,11 +111,11 @@ local function dump(inputfile)
> local reader = bufread.new(inputfile)
> local symbols = symtab.parse(reader)
> local events = memprof.parse(reader, symbols)
> - if not leak_only then
> - view.profile_info(events)
> + if not config.leak_only then
> + view.profile_info(events, config)
> end
> local dheap = process.form_heap_delta(events)
> - view.leak_info(dheap)
> + view.leak_info(dheap, config)
> view.aliases(symbols)
> -- XXX: The second argument is required to properly close Lua
> -- universe (i.e. invoke <lua_close> before exiting).
> diff --git a/tools/memprof/humanize.lua b/tools/memprof/humanize.lua
> index 5b289ce3..a0b1693a 100644
> --- a/tools/memprof/humanize.lua
> +++ b/tools/memprof/humanize.lua
> @@ -5,7 +5,29 @@
>
> local M = {}
>
> -function M.render(events)
> +local function human_readable_bytes(bytes)
> + local units = {"B", "KiB", "MiB", "GiB"}
> + local magnitude = 1
> +
> + while bytes >= 1024 and magnitude < #units do
> + bytes = bytes / 1024
> + magnitude = magnitude + 1
> + end
> + local is_int = math.floor(bytes) == bytes
> + local fmt = is_int and "%d%s" or "%.2f%s"
> +
> + return string.format(fmt, bytes, units[magnitude])
> +end
> +
> +local function format_bytes(bytes, config)
> + if config.human_readable then
> + return human_readable_bytes(bytes)
> + else
> + return string.format('%dB', bytes)
> + end
> +end
> +
> +function M.render(events, config)
> local ids = {}
>
> for id, _ in pairs(events) do
> @@ -18,11 +40,11 @@ function M.render(events)
>
> for i = 1, #ids do
> local event = events[ids[i]]
> - print(string.format("%s: %d events\t+%d bytes\t-%d bytes",
> + print(string.format("%s: %d events\t+%s\t-%s",
> event.loc,
> event.num,
> - event.alloc,
> - event.free
> + format_bytes(event.alloc, config),
> + format_bytes(event.free, config)
> ))
>
> local prim_loc = {}
> @@ -40,21 +62,21 @@ function M.render(events)
> end
> end
>
> -function M.profile_info(events)
> +function M.profile_info(events, config)
> print("ALLOCATIONS")
> - M.render(events.alloc)
> + M.render(events.alloc, config)
> print("")
>
> print("REALLOCATIONS")
> - M.render(events.realloc)
> + M.render(events.realloc, config)
> print("")
>
> print("DEALLOCATIONS")
> - M.render(events.free)
> + M.render(events.free, config)
> print("")
> end
>
> -function M.leak_info(dheap)
> +function M.leak_info(dheap, config)
> local leaks = {}
> for line, info in pairs(dheap) do
> -- Report "INTERNAL" events inconsistencies for profiling
> @@ -71,8 +93,10 @@ function M.leak_info(dheap)
> print("HEAP SUMMARY:")
> for _, l in pairs(leaks) do
> print(string.format(
> - "%s holds %d bytes: %d allocs, %d frees",
> - l.line, l.dbytes, dheap[l.line].nalloc,
> + "%s holds %s: %d allocs, %d frees",
> + l.line,
> + format_bytes(l.dbytes, config),
> + dheap[l.line].nalloc,
> dheap[l.line].nfree
> ))
> end
next prev parent reply other threads:[~2023-12-20 12:24 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-06 18:55 [Tarantool-patches] [PATCH luajit v2 0/6] profilers: refactor parsers Maxim Kokryashkin via Tarantool-patches
2023-12-06 18:55 ` [Tarantool-patches] [PATCH luajit v2 1/6] build: purge sysprof.collapse module Maxim Kokryashkin via Tarantool-patches
2023-12-12 10:18 ` Sergey Kaplun via Tarantool-patches
2023-12-19 12:20 ` Sergey Bronnikov via Tarantool-patches
2023-12-06 18:55 ` [Tarantool-patches] [PATCH luajit v2 2/6] build: fix tool components handling Maxim Kokryashkin via Tarantool-patches
2023-12-12 10:32 ` Sergey Kaplun via Tarantool-patches
2023-12-12 12:53 ` Maxim Kokryashkin via Tarantool-patches
2023-12-12 12:51 ` Sergey Kaplun via Tarantool-patches
2023-12-19 13:56 ` Sergey Bronnikov via Tarantool-patches
2023-12-06 18:55 ` [Tarantool-patches] [PATCH luajit v2 3/6] memprof: refactor `heap_chunk` data structure Maxim Kokryashkin via Tarantool-patches
2023-12-12 10:34 ` Sergey Kaplun via Tarantool-patches
2023-12-19 14:00 ` Sergey Bronnikov via Tarantool-patches
2023-12-06 18:55 ` [Tarantool-patches] [PATCH luajit v2 4/6] memprof: remove unused arguments Maxim Kokryashkin via Tarantool-patches
2023-12-12 10:44 ` Sergey Kaplun via Tarantool-patches
2023-12-19 14:01 ` Sergey Bronnikov via Tarantool-patches
2023-12-06 18:55 ` [Tarantool-patches] [PATCH luajit v2 5/6] memprof: introduce the `--human-readable` option Maxim Kokryashkin via Tarantool-patches
2023-12-12 10:54 ` Sergey Kaplun via Tarantool-patches
2023-12-20 12:24 ` Sergey Bronnikov via Tarantool-patches [this message]
2023-12-06 18:55 ` [Tarantool-patches] [PATCH luajit v2 6/6] profilers: print user-friendly errors Maxim Kokryashkin via Tarantool-patches
2023-12-12 11:51 ` Sergey Kaplun via Tarantool-patches
2023-12-12 12:54 ` Maxim Kokryashkin via Tarantool-patches
2023-12-12 12:54 ` Sergey Kaplun via Tarantool-patches
2023-12-29 12:27 ` Sergey Bronnikov via Tarantool-patches
2024-01-09 13:54 ` Maxim Kokryashkin via Tarantool-patches
2024-01-16 9:48 ` Sergey Bronnikov via Tarantool-patches
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ef8ed77b-5cc2-4816-af0c-95c84905a579@tarantool.org \
--to=tarantool-patches@dev.tarantool.org \
--cc=max.kokryashkin@gmail.com \
--cc=sergeyb@tarantool.org \
--cc=skaplun@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH luajit v2 5/6] memprof: introduce the `--human-readable` option' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox