From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1E320E77198 for ; Wed, 8 Jan 2025 01:17:27 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 832776B0083; Tue, 7 Jan 2025 20:17:27 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 7E2B96B0089; Tue, 7 Jan 2025 20:17:27 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 682EB6B008A; Tue, 7 Jan 2025 20:17:27 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 4504F6B0083 for ; Tue, 7 Jan 2025 20:17:27 -0500 (EST) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id ED0531A0EDF for ; Wed, 8 Jan 2025 01:17:26 +0000 (UTC) X-FDA: 82982521692.24.461E733 Received: from out-189.mta1.migadu.com (out-189.mta1.migadu.com [95.215.58.189]) by imf27.hostedemail.com (Postfix) with ESMTP id 7564840003 for ; Wed, 8 Jan 2025 01:17:23 +0000 (UTC) Authentication-Results: imf27.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=WcYzpgPP; spf=pass (imf27.hostedemail.com: domain of hao.ge@linux.dev designates 95.215.58.189 as permitted sender) smtp.mailfrom=hao.ge@linux.dev; dmarc=pass (policy=none) header.from=linux.dev ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1736299043; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=Sx+3BcpPBynVAYjBZAaSdn6VuQrU/XPzfSWGVAzYPZ4=; b=K5peeN5gVYnNY404+oPNpYz32dFCPJPt/JZjAb5G7vM4RVoG80Pks0itH3uV+83G+FJnEr 290a0fARfSYawiWm1pDTW2DSoC+TvSN3jcEEKuXxnu2ji0qieI8QbW2IweuDJTiIRyBoaj 7ZfW0KHAXZEupEbORF3FsevFmG7cCSE= ARC-Authentication-Results: i=1; imf27.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=WcYzpgPP; spf=pass (imf27.hostedemail.com: domain of hao.ge@linux.dev designates 95.215.58.189 as permitted sender) smtp.mailfrom=hao.ge@linux.dev; dmarc=pass (policy=none) header.from=linux.dev ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1736299043; a=rsa-sha256; cv=none; b=5/Vh4GSVwnBahJrnnraGCltjL2l90Hus83q5IMepfeEdEKALjFC59gwONESxDG3iJWSVa+ oWhLLID5Ug+K+uhZczRMjf+H2zwZDrZ8HifIW9snEhsTBHFyYRYFio3Yv1Ig/gjqF6K//l SMN4kceLJ+5zxrTrAh7H7acX7sm9nls= Content-Type: multipart/alternative; boundary="------------MBxOPzuLeL7nX0JAqgCgSxH8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1736299041; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=Sx+3BcpPBynVAYjBZAaSdn6VuQrU/XPzfSWGVAzYPZ4=; b=WcYzpgPPHn2Ri+2Bu78yv7LePrLlEJv4P/Zbx7aY0RBpd+GxDs+/LOqeUPY+wrLgHIaVnV qu+2mdyA3J9MtM2EvnGxcAZWe+3Mw2UI9fHknoG/IXI+1rmUnp0r6JxO1hToiJTfYDHmuN LO9K57rYQOzwMM2V5lFKOk3Yxbk7vaI= Message-ID: Date: Wed, 8 Jan 2025 09:16:27 +0800 MIME-Version: 1.0 Subject: Re: [PATCH] tools/mm: Introduce a tool to handle entries in allocinfo To: Alessio Balsini , Suren Baghdasaryan Cc: akpm@linux-foundation.org, kent.overstreet@linux.dev, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Hao Ge , Alessio Balsini , Pasha Tatashin , Sourav Panda , David Wang <00107082@163.com> References: <20250106112103.25401-1-hao.ge@linux.dev> Content-Language: en-US X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: Hao Ge In-Reply-To: X-Migadu-Flow: FLOW_OUT X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: 7564840003 X-Rspam-User: X-Stat-Signature: 6hzt8xs1o3q5n884jjrsmip78zwjmwpr X-HE-Tag: 1736299043-143185 X-HE-Meta: U2FsdGVkX1+P0EgOEV7y9/WFSMZMYu8s3dpRtfBzYYYOG4AAAN9dqgnGBamdmx6zNn3/nxZBzKWFmhtOdyOOIRhm54N3EttM7IgAwDSf2xLgmdHI+bEyb/mAhuxC6CejHHVmewNu7+Tu7XUePFW03CrmlxIjVA0zr/KQUnCAv4TigD7GOKbfHna5HK1uI1ayJTfroCIWlr6gK8Xqnc2RWNvDIGh2hONRVN/1/kwdr5amdPkS7gHlxZG7B5rnvPxJiWEPJQbMmwjC0IbSFRtsA7+BU8sZiFvWRBxLBFM5oef6uzaEhS9kMjA4o9wP9c0bd4jObyFUTvs7RhaUhV0HBy6pftRbkt4L6WqfcyzIGdIGMQ9oGF906FuhgqW2BbH2/o0RofrTironM1lNgsc6CkTCKkNjkcybTeFYJJG7z1hNSg+aGYtiqxPsgEMUwWSfSzB6SSTgtZ9BuXDtGiwK1cGlwrYeofPw+LhG+I5VM4IcIum35XnoxQl9bfeYjV4IQYd1ZvZq+ChpmL7CxPucfPk/jTDQ4eCeJXK19xk1yT5dnIH03V2YXXXT+Iaybjjheeq0Hl/HeMiaTphWPs799bhlgNVzeoAn51kxT6ejtWHcavD01ObV7Tz5tke1LJAlCA09zJRqKPLqtuzXGCs8nXzAMz4wd9EBtTEqFFrsvojD+Dx7eIxR1qFgDTGuwztM1Kio8xmKcITYMA5JBaVR0gY9QHaB53m//P1SXfoybp2B6wG4xt5DnJ2hiIRccabEqxXwcymLTrPEC9CrmyKpHcDbFB5zoGkA8Etb1SOUE+Ivqq2eS0r/OpF08/ezzFnBy0z4ktUBa2xv232ARPm4Y6GN/UfBuGVweTGmmuvEi60zNhvsFCe85uhdOUEIWThfkrIGq4zj6U/5DMFyr7RnwVNmCdLwMAyXRI5uHR1ANjbQoKiv4WxB80D7uSbhKmhkw/9R+t0QzLMFwPtqvGh Yxnp7tsZ hJpjoH/ZSzaq39sGrdnFAJoKQivs1TcTc9EfYhMcoiWzR+HKx3YhLzymoWEoRTkWUrvruYaSIHAmEUdlrkeiJc1+yUIovh0XU/lF5e8qCkFNG2WodDS4D5PAp1xDeBXs06RHi+fg7Jp3/F7m8wIjc0bfL1veF6dYMkMeFFJeAqEeT0o874hrgi5Ntlkgr30/mteUi0/lY3289+ztgglVyLslhq5+uf6tVCt0OONeMvDjNji3K0TOvI+0WXDQUqvuS4lfpiUG+ThFFgIfWg2MeNLi7PnaNOD9FtMscSrZX4zpoX8X9FOAs1bL9q01bxp1BJXJ9DukChwd3XTcFrFao7XS7NlQKZl60dsJi6R+Qnqk2WOXv40XFzk800jC+X6bISLt78EARib10BUtGfROkH6lFnM1hv/ar8lQM4XxcqBf4qgKYxv0MVNwEEg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: This is a multi-part message in MIME format. --------------MBxOPzuLeL7nX0JAqgCgSxH8 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hi Suren and Alessio Thanks for your information. On 2025/1/7 23:11, Alessio Balsini wrote: > Thank you Suren for looping me in and Hao for the tool! > > As Suren mentioned, we recently developed `alloctop` for the same reason as > yours: easy and fast manipulation of `/proc/allocinfo` instead of having long > chains of piped sorts, greps, awks... > `alloctop` takes `slabtop` as a reference for command line parameters and > output format. > It currently supports sorting and filtering by minimum allocation size, as well > as some kind of aggregation based on tag (similar to what `du` does). Yes, I originally intended to gradually add such functionalities as well as those discovered during subsequent usage. > As Suren mentioned, the tool is currently being tested on Android, but we would > be happy to collaborate on adding new features and making it part of tools/mm. I'm also happy to do this. I salute everyone who has put in the effort for this. Make this tool increasingly user-friendly. Thanks Best Regards Hao > > Thanks, > Alessio > > On Mon, Jan 6, 2025 at 9:12 PM Suren Baghdasaryan wrote: >> On Mon, Jan 6, 2025 at 3:22 AM Hao Ge wrote: >>> From: Hao Ge >>> >>> Some users always say that the information provided by /proc/allocinfo >>> is too extensive or bulky. >>> >>> However, from allocinfo's own perspective, it is not at fault as it >>> needs to provide comprehensive information. Users can then select the >>> information that is useful to them based on their own needs. >>> >>> For commonly used scenarios, we can develop a tool to facilitate users in >>> filtering and utilizing relevant information from allocinfo. >>> >>> Currently, there is only one filtering feature available, which is to >>> filter out entries where the 'bytes' field is 0 (since it is often used >>> to understand the current memory allocation status, as previously >>> mentioned by David Wang, who noticed that 2/3 of the lines have an >>> accumulative counter of 0, indicating no memory activities,it will fill >>> up the entire screen,by using the "-s" parameter, a lot of unnecessary >>> information for this scenario can be filtered out.) >>> >>> In subsequent phases, we will continue to add more features to this tool, >>> with the goal of making it convenient for most people to use the memory >>> allocation profiling tool. >> CC'ing Alessio along with Pasha and Sourav who were interested in such a tool. >> >> Hi Hao, >> Thanks for the tool! Actually Alessio just developed a tool called >> alloctop (similar to slabtop) which I think will do what you want and >> more. It supports sorting, filtering, continuous update, etc. It's >> written in Rust and we are planning to upstream it once we finish >> testing and evaluating it on Android. Please take a look and see if it >> fits your usecase. Please also note that this tool has been >> implemented just last week, so hot off the press and might have some >> early bugs. >> Thanks, >> Suren. >> >> [1]https://cs.android.com/android/platform/superproject/main/+/main:system/memory/libmeminfo/tools/alloctop/src/ >> >>> Signed-off-by: Hao Ge >>> --- >>> MAINTAINERS | 1 + >>> tools/mm/Makefile | 4 +- >>> tools/mm/allocinfo_tool.c | 150 ++++++++++++++++++++++++++++++++++++++ >>> 3 files changed, 153 insertions(+), 2 deletions(-) >>> create mode 100644 tools/mm/allocinfo_tool.c >>> >>> diff --git a/MAINTAINERS b/MAINTAINERS >>> index 910305c11e8a..cfc3f9f0c046 100644 >>> --- a/MAINTAINERS >>> +++ b/MAINTAINERS >>> @@ -15000,6 +15000,7 @@ F: Documentation/mm/allocation-profiling.rst >>> F: include/linux/alloc_tag.h >>> F: include/linux/pgalloc_tag.h >>> F: lib/alloc_tag.c >>> +F: tools/mm/allocinfo_tool.c >>> >>> MEMORY CONTROLLER DRIVERS >>> M: Krzysztof Kozlowski >>> diff --git a/tools/mm/Makefile b/tools/mm/Makefile >>> index f5725b5c23aa..f669d534a82b 100644 >>> --- a/tools/mm/Makefile >>> +++ b/tools/mm/Makefile >>> @@ -3,7 +3,7 @@ >>> # >>> include ../scripts/Makefile.include >>> >>> -BUILD_TARGETS=page-types slabinfo page_owner_sort thp_swap_allocator_test >>> +BUILD_TARGETS=page-types slabinfo page_owner_sort thp_swap_allocator_test allocinfo_tool >>> INSTALL_TARGETS = $(BUILD_TARGETS) thpmaps >>> >>> LIB_DIR = ../lib/api >>> @@ -23,7 +23,7 @@ $(LIBS): >>> $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) >>> >>> clean: >>> - $(RM) page-types slabinfo page_owner_sort thp_swap_allocator_test >>> + $(RM) page-types slabinfo page_owner_sort thp_swap_allocator_test allocinfo_tool >>> make -C $(LIB_DIR) clean >>> >>> sbindir ?= /usr/sbin >>> diff --git a/tools/mm/allocinfo_tool.c b/tools/mm/allocinfo_tool.c >>> new file mode 100644 >>> index 000000000000..817f46d07a50 >>> --- /dev/null >>> +++ b/tools/mm/allocinfo_tool.c >>> @@ -0,0 +1,150 @@ >>> +// SPDX-License-Identifier: GPL-2.0 >>> +/* >>> + * allocinfo_tool: Tool to parse allocinfo >>> + * >>> + * Authors: Hao Ge >>> + * >>> + * Compile with: >>> + * gcc -o allocinfo_tool allocinfo_tool.c >>> + */ >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#define ALLOCINFO_FILE "/proc/allocinfo" >>> +#define BUF_SIZE 1024 >>> +#define NAME_MAX_LENTH 64 >>> + >>> +struct alloc_tag_counters { >>> + signed long long bytes; >>> + unsigned long long calls; >>> +}; >>> + >>> +struct codetag { >>> + unsigned int lineno; >>> + char modname[NAME_MAX_LENTH]; >>> + char function[NAME_MAX_LENTH]; >>> + char filename[NAME_MAX_LENTH]; >>> +}; >>> + >>> +struct alloc_info { >>> + struct alloc_tag_counters counters; >>> + struct codetag tag; >>> + int has_modname; >>> +}; >>> + >>> +static int arg_opt; >>> + >>> +enum OPT_BIT { >>> + SKIP_ZERO = 1 << 0, >>> +}; >>> + >>> +void usage(void) >>> +{ >>> + printf("Usage: ./allocinfo_tool [OPTIONS]\n" >>> + "-s\t\t\tskip bytes for 0 allocinfo entries\n" >>> + ); >>> +} >>> + >>> +int parse_alloc_info(char *line, struct alloc_info *info) >>> +{ >>> + if (sscanf(line, "%12lli %8llu %[^:]:%d [%[^]]] func:%s", >>> + &info->counters.bytes, &info->counters.calls, >>> + info->tag.filename, &info->tag.lineno, >>> + info->tag.modname, info->tag.function) == 6){ >>> + info->has_modname = 1; >>> + return 1; >>> + }; >>> + >>> + if (sscanf(line, "%12llu %8llu %[^:]:%u func:%s", >>> + &info->counters.bytes, &info->counters.calls, >>> + info->tag.filename, &info->tag.lineno, >>> + info->tag.function) == 5){ >>> + info->has_modname = 0; >>> + return 1; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +int read_alloc_info(void) >>> +{ >>> + FILE *file = fopen(ALLOCINFO_FILE, "r"); >>> + >>> + if (!file) { >>> + perror("Failed to open /proc/allocinfo"); >>> + return EXIT_FAILURE; >>> + } >>> + >>> + int line = 0, i = 0; >>> + char *buffer = malloc(BUF_SIZE); >>> + struct alloc_info *info; >>> + >>> + while (fgets(buffer, BUF_SIZE, file)) { >>> + >>> + /* >>> + * allocinfo - version: 1.0 >>> + * # >>> + */ >>> + if (line < 2) { >>> + printf("%s", buffer); >>> + line++; >>> + continue; >>> + } >>> + >>> + info = realloc(info, sizeof(struct alloc_info) * (i + 1)); >>> + >>> + if (parse_alloc_info(buffer, info + i) == 0) { >>> + printf("Mismatch with the format of /proc/allocinfo"); >>> + return 0; >>> + } >>> + >>> + if ((arg_opt & SKIP_ZERO) && (info[i].counters.bytes == 0)) >>> + continue; >>> + >>> + printf("%12lli %8llu ", info[i].counters.bytes, info[i].counters.calls); >>> + >>> + if (info[i].has_modname) >>> + printf("%s:%u [%s] func:%s", >>> + info[i].tag.filename, info[i].tag.lineno, >>> + info[i].tag.modname, info[i].tag.function); >>> + else >>> + printf("%s:%u func:%s", >>> + info[i].tag.filename, info[i].tag.lineno, >>> + info[i].tag.function); >>> + printf(" "); >>> + printf("\n"); >>> + i++; >>> + } >>> + >>> + free(info); >>> + free(buffer); >>> + fclose(file); >>> +} >>> + >>> +int main(int argc, char *argv[]) >>> +{ >>> + >>> + int opt; >>> + struct option longopts[] = { >>> + { "s", 0, NULL, 1}, >>> + { 0, 0, 0, 0}, >>> + }; >>> + >>> + while ((opt = getopt_long(argc, argv, "s", longopts, NULL)) != -1) { >>> + switch (opt) { >>> + case 's': >>> + arg_opt = arg_opt | SKIP_ZERO; >>> + break; >>> + default: >>> + usage(); >>> + exit(1); >>> + } >>> + } >>> + >>> + read_alloc_info(); >>> + >>> +} >>> -- >>> 2.25.1 >>> --------------MBxOPzuLeL7nX0JAqgCgSxH8 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

Hi Suren and Alessio


Thanks for your information.


On 2025/1/7 23:11, Alessio Balsini wrote:
Thank you Suren for looping =
me in and Hao for the tool!

As Suren mentioned, we recently developed `alloctop` for the same reason =
as
yours: easy and fast manipulation of `/proc/allocinfo` instead of having =
long
chains of piped sorts, greps, awks...
`alloctop` takes `slabtop` as a reference for command line parameters and=

output format.
It currently supports sorting and filtering by minimum allocation size, a=
s well
as some kind of aggregation based on tag (similar to what `du` does).
    


Yes, I originally intended to gradually= add such functionalities as well as those

discovered during subsequent usage.


As Suren mentioned, the tool is currently being tested on Android, but we=
 would
be happy to collaborate on adding new features and making it part of tool=
s/mm.


I'm also happy to do this.

I salute everyone who has put in the ef= fort for this.

Make this tool increasingly user-friend= ly.

Thanks Best Regards Hao


Thanks,
Alessio

On Mon, Jan 6, 2025 at 9:12=E2=80=AFPM Suren Baghdasaryan <surenb@google.c=
om> wrote:
On Mon, Jan 6, 2025 at 3:22=E2=80=AFAM Hao Ge <hao.ge@linux.dev> wro=
te:
From: Hao Ge <gehao@kylinos.cn>

Some users always say that the information provided by /proc/allocinfo
is too extensive or bulky.

However, from allocinfo's own perspective, it is not at fault as it
needs to provide comprehensive information. Users can then select the
information that is useful to them based on their own needs.

For commonly used scenarios, we can develop a tool to facilitate users in=

filtering and utilizing relevant information from allocinfo.

Currently, there is only one filtering feature available, which is to
filter out entries where the 'bytes' field is 0 (since it is often used
to understand the current memory allocation status, as previously
mentioned by David Wang, who noticed that 2/3 of the lines have an
accumulative counter of 0, indicating no memory activities,it will fill
up the entire screen,by using the "-s" parameter, a lot of unnecessary
information for this scenario can be filtered out.)

In subsequent phases, we will continue to add more features to this tool,=

with the goal of making it convenient for most people to use the memory
allocation profiling tool.
CC'ing Alessio along with Pasha and Sourav who were interested in such a =
tool.

Hi Hao,
Thanks for the tool! Actually Alessio just developed a tool called
alloctop (similar to slabtop) which I think will do what you want and
more. It supports sorting, filtering, continuous update, etc. It's
written in Rust and we are planning to upstream it once we finish
testing and evaluating it on Android. Please take a look and see if it
fits your usecase. Please also note that this tool has been
implemented just last week, so hot off the press and might have some
early bugs.
Thanks,
Suren.

[1] https://cs.android.com/android/platform/superproject/main/+/m=
ain:system/memory/libmeminfo/tools/alloctop/src/

Signed-off-by: Hao Ge <gehao@kylinos.cn>
---
 MAINTAINERS               |   1 +
 tools/mm/Makefile         |   4 +-
 tools/mm/allocinfo_tool.c | 150 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 153 insertions(+), 2 deletions(-)
 create mode 100644 tools/mm/allocinfo_tool.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 910305c11e8a..cfc3f9f0c046 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15000,6 +15000,7 @@ F:      Documentation/mm/allocation-profiling.rst=

 F:     include/linux/alloc_tag.h
 F:     include/linux/pgalloc_tag.h
 F:     lib/alloc_tag.c
+F:     tools/mm/allocinfo_tool.c

 MEMORY CONTROLLER DRIVERS
 M:     Krzysztof Kozlowski <krzk@kernel.org>
diff --git a/tools/mm/Makefile b/tools/mm/Makefile
index f5725b5c23aa..f669d534a82b 100644
--- a/tools/mm/Makefile
+++ b/tools/mm/Makefile
@@ -3,7 +3,7 @@
 #
 include ../scripts/Makefile.include

-BUILD_TARGETS=3Dpage-types slabinfo page_owner_sort thp_swap_allocator_t=
est
+BUILD_TARGETS=3Dpage-types slabinfo page_owner_sort thp_swap_allocator_t=
est allocinfo_tool
 INSTALL_TARGETS =3D $(BUILD_TARGETS) thpmaps

 LIB_DIR =3D ../lib/api
@@ -23,7 +23,7 @@ $(LIBS):
        $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

 clean:
-       $(RM) page-types slabinfo page_owner_sort thp_swap_allocator_test=

+       $(RM) page-types slabinfo page_owner_sort thp_swap_allocator_test=
 allocinfo_tool
        make -C $(LIB_DIR) clean

 sbindir ?=3D /usr/sbin
diff --git a/tools/mm/allocinfo_tool.c b/tools/mm/allocinfo_tool.c
new file mode 100644
index 000000000000..817f46d07a50
--- /dev/null
+++ b/tools/mm/allocinfo_tool.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * allocinfo_tool: Tool to parse allocinfo
+ *
+ * Authors: Hao Ge <hao.ge@linux.dev>
+ *
+ * Compile with:
+ * gcc -o allocinfo_tool allocinfo_tool.c
+ */
+
+#include<stdio.h>
+#include<stdlib.h>
+#include<sys/stat.h>
+#include <string.h>
+#include <getopt.h>
+
+#define ALLOCINFO_FILE "/proc/allocinfo"
+#define BUF_SIZE 1024
+#define NAME_MAX_LENTH 64
+
+struct alloc_tag_counters {
+       signed long long bytes;
+       unsigned long long calls;
+};
+
+struct codetag {
+       unsigned int lineno;
+       char modname[NAME_MAX_LENTH];
+       char function[NAME_MAX_LENTH];
+       char filename[NAME_MAX_LENTH];
+};
+
+struct alloc_info {
+       struct alloc_tag_counters counters;
+       struct codetag tag;
+       int has_modname;
+};
+
+static int arg_opt;
+
+enum OPT_BIT {
+       SKIP_ZERO =3D 1 << 0,
+};
+
+void usage(void)
+{
+       printf("Usage: ./allocinfo_tool [OPTIONS]\n"
+              "-s\t\t\tskip bytes for 0 allocinfo entries\n"
+       );
+}
+
+int parse_alloc_info(char *line, struct alloc_info *info)
+{
+       if (sscanf(line, "%12lli %8llu %[^:]:%d [%[^]]] func:%s",
+                     &info->counters.bytes, &info->counter=
s.calls,
+                     info->tag.filename, &info->tag.lineno,
+                     info->tag.modname, info->tag.function) =3D=3D=
 6){
+               info->has_modname =3D 1;
+               return 1;
+       };
+
+       if (sscanf(line, "%12llu %8llu %[^:]:%u func:%s",
+                  &info->counters.bytes, &info->counters.c=
alls,
+                  info->tag.filename, &info->tag.lineno,
+                  info->tag.function) =3D=3D 5){
+               info->has_modname =3D 0;
+               return 1;
+       }
+
+       return 0;
+}
+
+int read_alloc_info(void)
+{
+       FILE *file =3D fopen(ALLOCINFO_FILE, "r");
+
+       if (!file) {
+               perror("Failed to open /proc/allocinfo");
+               return EXIT_FAILURE;
+       }
+
+       int line =3D 0, i =3D 0;
+       char *buffer =3D malloc(BUF_SIZE);
+       struct alloc_info *info;
+
+       while (fgets(buffer, BUF_SIZE, file)) {
+
+               /*
+                * allocinfo - version: 1.0
+                * #     <size>  <calls> <tag info>
+                */
+               if (line < 2) {
+                       printf("%s", buffer);
+                       line++;
+                       continue;
+               }
+
+               info =3D realloc(info, sizeof(struct alloc_info) * (i + 1=
));
+
+               if (parse_alloc_info(buffer, info + i) =3D=3D 0) {
+                       printf("Mismatch with the format of /proc/allocin=
fo");
+                       return 0;
+               }
+
+               if ((arg_opt & SKIP_ZERO) && (info[i].counter=
s.bytes =3D=3D 0))
+                       continue;
+
+               printf("%12lli %8llu ", info[i].counters.bytes, info[i].c=
ounters.calls);
+
+               if (info[i].has_modname)
+                       printf("%s:%u [%s] func:%s",
+                              info[i].tag.filename, info[i].tag.lineno,
+                              info[i].tag.modname, info[i].tag.function)=
;
+               else
+                       printf("%s:%u func:%s",
+                              info[i].tag.filename, info[i].tag.lineno,
+                              info[i].tag.function);
+               printf(" ");
+               printf("\n");
+               i++;
+       }
+
+       free(info);
+       free(buffer);
+       fclose(file);
+}
+
+int main(int argc, char *argv[])
+{
+
+       int opt;
+       struct option longopts[] =3D {
+               { "s", 0, NULL, 1},
+               { 0, 0, 0, 0},
+       };
+
+       while ((opt =3D getopt_long(argc, argv, "s", longopts, NULL)) !=3D=
 -1) {
+               switch (opt) {
+               case 's':
+                       arg_opt =3D arg_opt | SKIP_ZERO;
+                       break;
+               default:
+                       usage();
+                       exit(1);
+               }
+       }
+
+       read_alloc_info();
+
+}
--
2.25.1


      
--------------MBxOPzuLeL7nX0JAqgCgSxH8--