diff mbox series

[RFC,v1,2/2] tools/mm/slabinfo: add support for sheaves stats

Message ID 20250407041810.13861-3-harry.yoo@oracle.com (mailing list archive)
State New
Headers show
Series slabinfo: sheaves statistics support | expand

Commit Message

Harry Yoo April 7, 2025, 4:18 a.m. UTC
Add sheaves stats support to the slabinfo tool to make it easier to
investigate sheaves statistics.

"Served from sheaves" indicates the number of allocations and frees that
were served from sheaves, out of the total number of allocations and
frees (including those not using sheaves).

The other sheaves statistics reflect only the number of events among
allocations and frees that were served from sheaves.

Before:
$ sudo ./slabinfo -r maple_node
Slabcache: maple_node       Aliases:  0 Order :  1 Objects: 8433

[... snip ...]

Slab Perf Counter       Alloc     Free %Al %Fr
--------------------------------------------------
Fastpath               177539     3150  94   4
Slowpath                10841    72067   5  95
Page Alloc                903      519   0   0
Add partial                 0     8729   0  11
Remove partial           2007      420   1   0
Cpu partial list         7124     9999   3  13
RemoteObj/SlabFrozen        0     3041   0   4
Total                  188380    75217

Slab Deactivation             Occurrences %
-------------------------------------------------
Slab full                           0    0%
Slab empty                         99    0%
Moved to head of partial list       0    0%
Moved to tail of partial list       0    0%
Deactivation bypass             10012   99%
Refilled from foreign frees       807    7%
Node mismatch                       0    0%

After:
$ sudo ./slabinfo -r maple_node
Slabcache: maple_node       Aliases:  0 Order :  1 Objects: 8268

[... snip ...]

Slab Perf Counter       Alloc     Free %Al %Fr
----------------------------------------------
Fastpath               258760     5109  93   3
Slowpath                18205   126605   6  96
Page Alloc                903      520   0   0
Add partial                 0    14600   0  11
Remove partial           3472      420   1   0
Cpu partial list        12235    16577   4  12
RemoteObj/SlabFrozen        0     5969   0   4
Total                  276965   131714

Slab Sheaves Counter       Alloc    Free  %Al  %Fr  %Fa
-------------------------------------------------------
Served from sheaves     1805673   580161   86   93  N/A
Sheaves refill           236384      N/A   13  N/A  N/A
Sheaves alloc              3872     3794    0    0  N/A
Free to RCU sheaves         N/A  1255815  N/A   68    0
Main sheaf flush            N/A        0  N/A    0  N/A
Other sheaves flush         N/A   265600  N/A   14  N/A

Slab Deactivation             Occurrences %
-------------------------------------------
Slab full                           0    0%
Slab empty                        100    0%
Moved to head of partial list       0    0%
Moved to tail of partial list       0    0%
Deactivation bypass             16588   99%
Refilled from foreign frees      1595    9%
Node mismatch                       0    0%

Signed-off-by: Harry Yoo <harry.yoo@oracle.com>
---
 tools/mm/slabinfo.c | 62 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/tools/mm/slabinfo.c b/tools/mm/slabinfo.c
index 1433eff99feb..c930b2135b33 100644
--- a/tools/mm/slabinfo.c
+++ b/tools/mm/slabinfo.c
@@ -44,6 +44,12 @@  struct slabinfo {
 	unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail;
 	unsigned long alloc_node_mismatch, deactivate_bypass;
 	unsigned long cpu_partial_alloc, cpu_partial_free;
+	unsigned int sheaves_enabled;
+	unsigned long alloc_cpu_sheaf, free_cpu_sheaf;
+	unsigned long free_rcu_sheaf, free_rcu_sheaf_fail;
+	unsigned long sheaf_flush_main, sheaf_flush_other;
+	unsigned long sheaf_refill, sheaf_swap;
+	unsigned long sheaf_alloc, sheaf_free;
 	int numa[MAX_NODES];
 	int numa_partial[MAX_NODES];
 } slabinfo[MAX_SLABS];
@@ -472,6 +478,7 @@  static void slab_stats(struct slabinfo *s)
 	unsigned long total_alloc;
 	unsigned long total_free;
 	unsigned long total;
+	const char *not_avail = "N/A";
 
 	if (!s->alloc_slab)
 		return;
@@ -484,7 +491,7 @@  static void slab_stats(struct slabinfo *s)
 
 	printf("\n");
 	printf("Slab Perf Counter       Alloc     Free %%Al %%Fr\n");
-	printf("--------------------------------------------------\n");
+	printf("----------------------------------------------\n");
 	printf("Fastpath             %8lu %8lu %3lu %3lu\n",
 		s->alloc_fastpath, s->free_fastpath,
 		s->alloc_fastpath * 100 / total_alloc,
@@ -525,9 +532,47 @@  static void slab_stats(struct slabinfo *s)
 	total = s->deactivate_full + s->deactivate_empty +
 			s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass;
 
+	if (s->sheaves_enabled) {
+		unsigned long sheaves_total_alloc = s->alloc_cpu_sheaf;
+		unsigned long sheaves_total_free = s->free_cpu_sheaf + s->free_rcu_sheaf;
+
+		total_alloc += sheaves_total_alloc;
+		total_free += sheaves_total_free;
+
+		printf("\n");
+		printf("Slab Sheaves Counter       Alloc    Free  %%Al  %%Fr  %%Fa\n");
+		printf("-------------------------------------------------------\n");
+		printf("Served from sheaves    %8lu %8lu %4lu %4lu %4s\n",
+		       s->alloc_cpu_sheaf, s->free_cpu_sheaf,
+		       total_alloc ? sheaves_total_alloc * 100 / total_alloc : 0,
+		       total_free ? sheaves_total_free * 100 / total_free : 0,
+		       not_avail);
+		printf("Sheaves refill         %8lu %8s %4lu %4s %4s\n",
+		       s->sheaf_refill, not_avail,
+		       sheaves_total_alloc ? s->sheaf_refill * 100 / sheaves_total_alloc : 0,
+		       not_avail, not_avail);
+		printf("Sheaves alloc          %8lu %8lu %4lu %4lu %4s\n",
+		       s->sheaf_alloc, s->sheaf_free,
+		       sheaves_total_alloc ? s->sheaf_alloc * 100 / sheaves_total_alloc : 0,
+		       sheaves_total_free ? s->sheaf_free * 100 / sheaves_total_free : 0,
+		       not_avail);
+		printf("Free to RCU sheaves    %8s %8lu %4s %4lu %4lu\n",
+		       not_avail, s->free_rcu_sheaf, not_avail,
+		       sheaves_total_free ? s->free_rcu_sheaf * 100 / sheaves_total_free : 0,
+		       s->free_rcu_sheaf ? s->free_rcu_sheaf_fail * 100 / s->free_rcu_sheaf : 0);
+		printf("Main sheaf flush       %8s %8lu %4s %4lu %4s\n",
+		       not_avail, s->sheaf_flush_main, not_avail,
+		       sheaves_total_free ? s->sheaf_flush_main * 100 / sheaves_total_free : 0,
+		       not_avail);
+		printf("Other sheaves flush    %8s %8lu %4s %4lu %4s\n",
+		       not_avail, s->sheaf_flush_other, not_avail,
+		       sheaves_total_free ? s->sheaf_flush_other * 100 / sheaves_total_free : 0,
+		       not_avail);
+	}
+
 	if (total) {
 		printf("\nSlab Deactivation             Occurrences %%\n");
-		printf("-------------------------------------------------\n");
+		printf("-------------------------------------------\n");
 		printf("Slab full                     %7lu  %3lu%%\n",
 			s->deactivate_full, (s->deactivate_full * 100) / total);
 		printf("Slab empty                    %7lu  %3lu%%\n",
@@ -1301,6 +1346,19 @@  static void read_slab_dir(void)
 			slab->cpu_partial_free = get_obj("cpu_partial_free");
 			slab->alloc_node_mismatch = get_obj("alloc_node_mismatch");
 			slab->deactivate_bypass = get_obj("deactivate_bypass");
+			slab->sheaves_enabled = get_obj("sheaves_enabled");
+			if (slab->sheaves_enabled) {
+				slab->alloc_cpu_sheaf = get_obj("alloc_cpu_sheaf");
+				slab->free_cpu_sheaf = get_obj("free_cpu_sheaf");
+				slab->free_rcu_sheaf = get_obj("free_rcu_sheaf");
+				slab->free_rcu_sheaf_fail = get_obj("free_rcu_sheaf_fail");
+				slab->sheaf_flush_main = get_obj("sheaf_flush_main");
+				slab->sheaf_flush_other = get_obj("sheaf_flush_other");
+				slab->sheaf_refill = get_obj("sheaf_refill");
+				slab->sheaf_swap = get_obj("sheaf_swap");
+				slab->sheaf_alloc = get_obj("sheaf_alloc");
+				slab->sheaf_free = get_obj("sheaf_free");
+			}
 			if (chdir(".."))
 				fatal("Unable to chdir from slab ../%s\n",
 				      slab->name);