From d914999689609d45b36db2b0fabb05cf7fc1fa1f Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 11 Jul 2019 20:59:34 -0700 Subject: tools/vm/slabinfo: order command line options During recent discussion on LKML over SLAB vs SLUB it was suggested by Jesper that it would be nice to have a tool to view the current fragmentation of the slab allocators. CC list for this set is taken from that thread. For SLUB we have all the information for this already exposed by the kernel and also we have a userspace tool for displaying this info: tools/vm/slabinfo.c Extend slabinfo to improve the fragmentation information by enabling sorting of caches by number of partial slabs. Also add cache list sorted in this manner to the output of `slabinfo -X`. This patch (of 4): get_opt() has a spurious character within the option string. Remove it and reorder the options in alphabetic order so that it is easier to keep the options correct. Use the same ordering for command help output and long option handling code. Link: http://lkml.kernel.org/r/20190426022622.4089-2-tobin@kernel.org Signed-off-by: Tobin C. Harding Cc: Jesper Dangaard Brouer Cc: Pekka Enberg Cc: Vlastimil Babka Cc: Christoph Lameter Cc: David Rientjes Cc: Joonsoo Kim Cc: Tejun Heo Cc: Qian Cai Cc: Mel Gorman Cc: Alexander Duyck Cc: Michal Hocko Cc: Brendan Gregg , Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- tools/vm/slabinfo.c | 70 ++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'tools') diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c index 73818f1b2ef8..e9b5437b2f28 100644 --- a/tools/vm/slabinfo.c +++ b/tools/vm/slabinfo.c @@ -110,7 +110,7 @@ static void fatal(const char *x, ...) static void usage(void) { printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n" - "slabinfo [-aADefhilnosrStTvz1LXBU] [N=K] [-dafzput] [slab-regexp]\n" + "slabinfo [-aABDefhilLnorsStTUvXz1] [N=K] [-dafzput] [slab-regexp]\n" "-a|--aliases Show aliases\n" "-A|--activity Most active slabs first\n" "-B|--Bytes Show size in bytes\n" @@ -131,9 +131,9 @@ static void usage(void) "-T|--Totals Show summary information\n" "-U|--Unreclaim Show unreclaimable slabs only\n" "-v|--validate Validate slabs\n" + "-X|--Xtotals Show extended summary information\n" "-z|--zero Include empty slabs\n" "-1|--1ref Single reference\n" - "-X|--Xtotals Show extended summary information\n" "\n" "-d | --debug Switch off all debug options\n" @@ -1334,6 +1334,7 @@ static void xtotals(void) struct option opts[] = { { "aliases", no_argument, NULL, 'a' }, { "activity", no_argument, NULL, 'A' }, + { "Bytes", no_argument, NULL, 'B'}, { "debug", optional_argument, NULL, 'd' }, { "display-activity", no_argument, NULL, 'D' }, { "empty", no_argument, NULL, 'e' }, @@ -1341,21 +1342,20 @@ struct option opts[] = { { "help", no_argument, NULL, 'h' }, { "inverted", no_argument, NULL, 'i'}, { "slabs", no_argument, NULL, 'l' }, + { "Loss", no_argument, NULL, 'L'}, { "numa", no_argument, NULL, 'n' }, + { "lines", required_argument, NULL, 'N'}, { "ops", no_argument, NULL, 'o' }, - { "shrink", no_argument, NULL, 's' }, { "report", no_argument, NULL, 'r' }, + { "shrink", no_argument, NULL, 's' }, { "Size", no_argument, NULL, 'S'}, { "tracking", no_argument, NULL, 't'}, { "Totals", no_argument, NULL, 'T'}, + { "Unreclaim", no_argument, NULL, 'U'}, { "validate", no_argument, NULL, 'v' }, + { "Xtotals", no_argument, NULL, 'X'}, { "zero", no_argument, NULL, 'z' }, { "1ref", no_argument, NULL, '1'}, - { "lines", required_argument, NULL, 'N'}, - { "Loss", no_argument, NULL, 'L'}, - { "Xtotals", no_argument, NULL, 'X'}, - { "Bytes", no_argument, NULL, 'B'}, - { "Unreclaim", no_argument, NULL, 'U'}, { NULL, 0, NULL, 0 } }; @@ -1367,18 +1367,18 @@ int main(int argc, char *argv[]) page_size = getpagesize(); - while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTSN:LXBU", + while ((c = getopt_long(argc, argv, "aABd::DefhilLnN:orsStTUvXz1", opts, NULL)) != -1) switch (c) { - case '1': - show_single_ref = 1; - break; case 'a': show_alias = 1; break; case 'A': sort_active = 1; break; + case 'B': + show_bytes = 1; + break; case 'd': set_debug = 1; if (!debug_opt_scan(optarg)) @@ -1399,9 +1399,22 @@ int main(int argc, char *argv[]) case 'i': show_inverted = 1; break; + case 'l': + show_slab = 1; + break; + case 'L': + sort_loss = 1; + break; case 'n': show_numa = 1; break; + case 'N': + if (optarg) { + output_lines = atoi(optarg); + if (output_lines < 1) + output_lines = 1; + } + break; case 'o': show_ops = 1; break; @@ -1411,33 +1424,20 @@ int main(int argc, char *argv[]) case 's': shrink = 1; break; - case 'l': - show_slab = 1; + case 'S': + sort_size = 1; break; case 't': show_track = 1; break; - case 'v': - validate = 1; - break; - case 'z': - skip_zero = 0; - break; case 'T': show_totals = 1; break; - case 'S': - sort_size = 1; - break; - case 'N': - if (optarg) { - output_lines = atoi(optarg); - if (output_lines < 1) - output_lines = 1; - } + case 'U': + unreclaim_only = 1; break; - case 'L': - sort_loss = 1; + case 'v': + validate = 1; break; case 'X': if (output_lines == -1) @@ -1445,11 +1445,11 @@ int main(int argc, char *argv[]) extended_totals = 1; show_bytes = 1; break; - case 'B': - show_bytes = 1; + case 'z': + skip_zero = 0; break; - case 'U': - unreclaim_only = 1; + case '1': + show_single_ref = 1; break; default: fatal("%s: Invalid option '%c'\n", argv[0], optopt); -- cgit v1.2.3 From 1106b205a3fe034beafad24045b7c00a7eb89669 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 11 Jul 2019 20:59:38 -0700 Subject: tools/vm/slabinfo: add partial slab listing to -X We would like to see how fragmented the SLUB allocator is, one window into fragmentation is the total number of partial slabs. Currently `slabinfo -X` shows slabs sorted by loss and by size. We can use this option to also show slabs sorted by number of partial slabs. Option '-X' can be used in conjunction with '-N' to control the number of slabs shown e.g. list of top 5 slabs: slabinfo -X -N5 Add list of slabs ordered by number of partial slabs to output of `slabinfo -X`. Link: http://lkml.kernel.org/r/20190426022622.4089-3-tobin@kernel.org Signed-off-by: Tobin C. Harding Cc: Alexander Duyck Cc: Brendan Gregg , Cc: Christoph Lameter Cc: David Rientjes Cc: Jesper Dangaard Brouer Cc: Joonsoo Kim Cc: Mel Gorman Cc: Michal Hocko Cc: Pekka Enberg Cc: Qian Cai Cc: Tejun Heo Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- tools/vm/slabinfo.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) (limited to 'tools') diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c index e9b5437b2f28..3f3a2db65794 100644 --- a/tools/vm/slabinfo.c +++ b/tools/vm/slabinfo.c @@ -79,6 +79,7 @@ int sort_size; int sort_active; int set_debug; int show_ops; +int sort_partial; int show_activity; int output_lines = -1; int sort_loss; @@ -1047,6 +1048,8 @@ static void sort_slabs(void) result = slab_activity(s1) < slab_activity(s2); else if (sort_loss) result = slab_waste(s1) < slab_waste(s2); + else if (sort_partial) + result = s1->partial < s2->partial; else result = strcasecmp(s1->name, s2->name); @@ -1307,27 +1310,39 @@ static void output_slabs(void) } } +static void _xtotals(char *heading, char *underline, + int loss, int size, int partial) +{ + printf("%s%s", heading, underline); + line = 0; + sort_loss = loss; + sort_size = size; + sort_partial = partial; + sort_slabs(); + output_slabs(); +} + static void xtotals(void) { + char *heading, *underline; + totals(); link_slabs(); rename_slabs(); - printf("\nSlabs sorted by size\n"); - printf("--------------------\n"); - sort_loss = 0; - sort_size = 1; - sort_slabs(); - output_slabs(); + heading = "\nSlabs sorted by size\n"; + underline = "--------------------\n"; + _xtotals(heading, underline, 0, 1, 0); + + heading = "\nSlabs sorted by loss\n"; + underline = "--------------------\n"; + _xtotals(heading, underline, 1, 0, 0); + + heading = "\nSlabs sorted by number of partial slabs\n"; + underline = "---------------------------------------\n"; + _xtotals(heading, underline, 0, 0, 1); - printf("\nSlabs sorted by loss\n"); - printf("--------------------\n"); - line = 0; - sort_loss = 1; - sort_size = 0; - sort_slabs(); - output_slabs(); printf("\n"); } -- cgit v1.2.3 From 53a83f9766e33d6bf4e14d5592c1939777fb98db Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 11 Jul 2019 20:59:42 -0700 Subject: tools/vm/slabinfo: add option to sort by partial slabs We would like to get a better view of the level of fragmentation within the SLUB allocator. Total number of partial slabs is an indicator of fragmentation. Add a command line option (-P | --partial) to sort the slab list by total number of partial slabs. Link: http://lkml.kernel.org/r/20190426022622.4089-4-tobin@kernel.org Signed-off-by: Tobin C. Harding Cc: Alexander Duyck Cc: Brendan Gregg , Cc: Christoph Lameter Cc: David Rientjes Cc: Jesper Dangaard Brouer Cc: Joonsoo Kim Cc: Mel Gorman Cc: Michal Hocko Cc: Pekka Enberg Cc: Qian Cai Cc: Tejun Heo Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- tools/vm/slabinfo.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c index 3f3a2db65794..469ff6157986 100644 --- a/tools/vm/slabinfo.c +++ b/tools/vm/slabinfo.c @@ -111,7 +111,7 @@ static void fatal(const char *x, ...) static void usage(void) { printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n" - "slabinfo [-aABDefhilLnorsStTUvXz1] [N=K] [-dafzput] [slab-regexp]\n" + "slabinfo [-aABDefhilLnoPrsStTUvXz1] [N=K] [-dafzput] [slab-regexp]\n" "-a|--aliases Show aliases\n" "-A|--activity Most active slabs first\n" "-B|--Bytes Show size in bytes\n" @@ -125,6 +125,7 @@ static void usage(void) "-n|--numa Show NUMA information\n" "-N|--lines=K Show the first K slabs\n" "-o|--ops Show kmem_cache_ops\n" + "-P|--partial Sort by number of partial slabs\n" "-r|--report Detailed report on single slabs\n" "-s|--shrink Shrink slabs\n" "-S|--Size Sort by size\n" @@ -1361,6 +1362,7 @@ struct option opts[] = { { "numa", no_argument, NULL, 'n' }, { "lines", required_argument, NULL, 'N'}, { "ops", no_argument, NULL, 'o' }, + { "partial", no_argument, NULL, 'p'}, { "report", no_argument, NULL, 'r' }, { "shrink", no_argument, NULL, 's' }, { "Size", no_argument, NULL, 'S'}, @@ -1382,7 +1384,7 @@ int main(int argc, char *argv[]) page_size = getpagesize(); - while ((c = getopt_long(argc, argv, "aABd::DefhilLnN:orsStTUvXz1", + while ((c = getopt_long(argc, argv, "aABd::DefhilLnN:oPrsStTUvXz1", opts, NULL)) != -1) switch (c) { case 'a': @@ -1436,6 +1438,9 @@ int main(int argc, char *argv[]) case 'r': show_report = 1; break; + case 'P': + sort_partial = 1; + break; case 's': shrink = 1; break; -- cgit v1.2.3 From cbf800d9c7fb38d953ba8ae1bd27a6382114c32e Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 11 Jul 2019 20:59:46 -0700 Subject: tools/vm/slabinfo: add sorting info to help menu Passing more than one sorting option has undefined behaviour. Add an explicit statement as such to the help menu, this also has the advantage of highlighting all the sorting options. Link: http://lkml.kernel.org/r/20190426022622.4089-5-tobin@kernel.org Signed-off-by: Tobin C. Harding Cc: Alexander Duyck Cc: Brendan Gregg , Cc: Christoph Lameter Cc: David Rientjes Cc: Jesper Dangaard Brouer Cc: Joonsoo Kim Cc: Mel Gorman Cc: Michal Hocko Cc: Pekka Enberg Cc: Qian Cai Cc: Tejun Heo Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- tools/vm/slabinfo.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tools') diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c index 469ff6157986..68092d15e12b 100644 --- a/tools/vm/slabinfo.c +++ b/tools/vm/slabinfo.c @@ -148,6 +148,8 @@ static void usage(void) " p | P Poisoning\n" " u | U Tracking\n" " t | T Tracing\n" + + "\nSorting options (--Loss, --Size, --Partial) are mutually exclusive\n" ); } -- cgit v1.2.3