lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date: Wed, 17 Apr 2024 16:44:39 +0200
From: Olivier Blin <olivier.blin@...tathome.com>
To: linux-perf-users@...r.kernel.org
Cc: Olivier Blin <olivier.blin@...tathome.com>,
	Peter Zijlstra <peterz@...radead.org>,
	Ingo Molnar <mingo@...hat.com>,
	Arnaldo Carvalho de Melo <acme@...nel.org>,
	Namhyung Kim <namhyung@...nel.org>,
	Mark Rutland <mark.rutland@....com>,
	Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
	Jiri Olsa <jolsa@...nel.org>,
	Ian Rogers <irogers@...gle.com>,
	Adrian Hunter <adrian.hunter@...el.com>,
	"Liang, Kan" <kan.liang@...ux.intel.com>,
	linux-kernel@...r.kernel.org
Subject: [PATCH] perf kmem: Report net allocation bytes per entry

This allows to detect memory leaks more easily, by reporting net
allocation bytes per caller or pointer in a new column.

This also adds a "net" sort key, so that "perf kmem --caller -s net stat"
reports the main leakers first.

Signed-off-by: Olivier Blin <olivier.blin@...tathome.com>
---
 tools/perf/builtin-kmem.c | 54 ++++++++++++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 12 deletions(-)

diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 6fd95be5032b..59bdca64b22b 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -64,6 +64,7 @@ struct alloc_stat {
        u64     bytes_req;
        u64     bytes_alloc;
        u64     last_alloc;
+       s64     net_alloc;
        u32     hit;
        u32     pingpong;

@@ -118,6 +119,7 @@ static int insert_alloc_stat(unsigned long call_site, unsigned long ptr,
                data->hit = 1;
                data->bytes_req = bytes_req;
                data->bytes_alloc = bytes_alloc;
+               data->net_alloc = 0;

                rb_link_node(&data->node, parent, node);
                rb_insert_color(&data->node, &root_alloc_stat);
@@ -125,6 +127,7 @@ static int insert_alloc_stat(unsigned long call_site, unsigned long ptr,
        data->call_site = call_site;
        data->alloc_cpu = cpu;
        data->last_alloc = bytes_alloc;
+       data->net_alloc += bytes_alloc;

        return 0;
 }
@@ -163,11 +166,14 @@ static int insert_caller_stat(unsigned long call_site,
                data->hit = 1;
                data->bytes_req = bytes_req;
                data->bytes_alloc = bytes_alloc;
+               data->net_alloc = 0;

                rb_link_node(&data->node, parent, node);
                rb_insert_color(&data->node, &root_caller_stat);
        }

+       data->net_alloc += bytes_alloc;
+
        return 0;
 }

@@ -254,14 +260,19 @@ static int evsel__process_free_event(struct evsel *evsel, struct perf_sample *sa

        total_freed += s_alloc->last_alloc;

+       s_alloc->net_alloc -= s_alloc->last_alloc;
+
+       s_caller = search_alloc_stat(0, s_alloc->call_site,
+                                    &root_caller_stat,
+                                    slab_callsite_cmp);
+       if (!s_caller)
+               return -1;
+
+       s_caller->net_alloc -= s_alloc->last_alloc;
+
        if ((short)sample->cpu != s_alloc->alloc_cpu) {
                s_alloc->pingpong++;

-               s_caller = search_alloc_stat(0, s_alloc->call_site,
-                                            &root_caller_stat,
-                                            slab_callsite_cmp);
-               if (!s_caller)
-                       return -1;
                s_caller->pingpong++;
        }
        s_alloc->alloc_cpu = -1;
@@ -1010,10 +1021,10 @@ static void __print_slab_result(struct rb_root *root,
        struct rb_node *next;
        struct machine *machine = &session->machines.host;

-       printf("%.105s\n", graph_dotted_line);
+       printf("%.117s\n", graph_dotted_line);
        printf(" %-34s |",  is_caller ? "Callsite": "Alloc Ptr");
-       printf(" Total_alloc/Per | Total_req/Per   | Hit      | Ping-pong | Frag\n");
-       printf("%.105s\n", graph_dotted_line);
+       printf(" Total_alloc/Per | Total_req/Per   | Hit      | Net_alloc | Ping-pong | Frag\n");
+       printf("%.117s\n", graph_dotted_line);

        next = rb_first(root);

@@ -1039,12 +1050,13 @@ static void __print_slab_result(struct rb_root *root,
                        snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr);
                printf(" %-34s |", buf);

-               printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %9lu | %6.3f%%\n",
+               printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %9lld | %9lu | %6.3f%%\n",
                       (unsigned long long)data->bytes_alloc,
                       (unsigned long)data->bytes_alloc / data->hit,
                       (unsigned long long)data->bytes_req,
                       (unsigned long)data->bytes_req / data->hit,
                       (unsigned long)data->hit,
+                      (long long)data->net_alloc,
                       (unsigned long)data->pingpong,
                       fragmentation(data->bytes_req, data->bytes_alloc));

@@ -1052,9 +1064,9 @@ static void __print_slab_result(struct rb_root *root,
        }

        if (n_lines == -1)
-               printf(" ...                                | ...             | ...             | ...      | ...       | ...   \n");
+               printf(" ...                                | ...             | ...             | ...      | ...       | ...       | ...   \n");

-       printf("%.105s\n", graph_dotted_line);
+       printf("%.117s\n", graph_dotted_line);
 }

 static const char * const migrate_type_str[] = {
@@ -1496,6 +1508,23 @@ static struct sort_dimension bytes_sort_dimension = {
        .cmp    = bytes_cmp,
 };

+static int net_cmp(void *a, void *b)
+{
+       struct alloc_stat *l = a;
+       struct alloc_stat *r = b;
+
+       if (l->net_alloc < r->net_alloc)
+               return -1;
+       else if (l->net_alloc > r->net_alloc)
+               return 1;
+       return 0;
+}
+
+static struct sort_dimension net_sort_dimension = {
+       .name   = "net",
+       .cmp    = net_cmp,
+};
+
 static int frag_cmp(void *a, void *b)
 {
        double x, y;
@@ -1667,6 +1696,7 @@ static struct sort_dimension *slab_sorts[] = {
        &callsite_sort_dimension,
        &hit_sort_dimension,
        &bytes_sort_dimension,
+       &net_sort_dimension,
        &frag_sort_dimension,
        &pingpong_sort_dimension,
 };
@@ -1951,7 +1981,7 @@ int cmd_kmem(int argc, const char **argv)
        OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
                           "show per-allocation statistics", parse_alloc_opt),
        OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
-                    "sort by keys: ptr, callsite, bytes, hit, pingpong, frag, "
+                    "sort by keys: ptr, callsite, bytes, hit, net, pingpong, frag, "
                     "page, order, migtype, gfp", parse_sort_opt),
        OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
        OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
--
2.34.1

-- This message and any attachments herein are confidential, intended solely for the addressees and are SoftAtHome’s ownership. Any unauthorized use or dissemination is prohibited. If you are not the intended addressee of this message, please cancel it immediately and inform the sender.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ