From 279ca6fb04964938ea05413b63ec22ca232dfb9f Mon Sep 17 00:00:00 2001
From: Nikita Pettik <korablev@tarantool.org>
Date: Thu, 3 Jun 2021 20:04:54 +0300
Subject: [PATCH] memtx: provide correct stats calculation for allocators

Firstly, Allocator::stats() must accept callback function and its
argument to fulfill small interfaces.
Secondly, unify stats and store both system and small allocators
statistics in the same structure in order to use ::stats() method in
foreach_allocator() helper.

Follow-up #5419
---
 src/box/allocator.cc    | 21 ++++++++++++++++++
 src/box/allocator.h     | 48 +++++++++++++++++++++++++++++------------
 src/box/lua/slab.cc     | 23 +++++++++++---------
 src/box/memtx_engine.cc | 10 ++++-----
 4 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/src/box/allocator.cc b/src/box/allocator.cc
index 3df6adcc6c..a8cd87ab55 100644
--- a/src/box/allocator.cc
+++ b/src/box/allocator.cc
@@ -32,3 +32,24 @@
 
 struct small_alloc SmallAlloc::small_alloc;
 struct sys_alloc SysAlloc::sys_alloc;
+
+int
+small_stats_noop_cb(const struct mempool_stats *stats, void *cb_ctx)
+{
+	(void) stats;
+	(void) cb_ctx;
+	return 0;
+}
+
+void
+allocators_stats(struct allocator_stats *stats, mempool_stats_cb cb,
+		 void *cb_ctx) {
+	foreach_allocator<allocator_stat,
+		struct allocator_stats *&, mempool_stats_cb&, void *&>
+			(stats, cb, cb_ctx);
+}
+
+void
+allocators_stats(struct allocator_stats *stats) {
+	allocators_stats(stats, small_stats_noop_cb, nullptr);
+}
diff --git a/src/box/allocator.h b/src/box/allocator.h
index 19e8a119d7..ef891ae4eb 100644
--- a/src/box/allocator.h
+++ b/src/box/allocator.h
@@ -34,18 +34,18 @@
 #include <small/small.h>
 #include "sysalloc.h"
 
-struct alloc_stats {
+struct alloc_stat {
 	size_t used;
 	size_t total;
 };
 
-static int
-small_stats_noop_cb(const struct mempool_stats *stats, void *cb_ctx)
-{
-	(void)stats;
-	(void)cb_ctx;
-	return 0;
-}
+struct allocator_stats {
+	struct alloc_stat small;
+	struct alloc_stat sys;
+};
+
+int
+small_stats_noop_cb(const struct mempool_stats *stats, void *cb_ctx);
 
 struct allocator_settings {
 	struct small_allocator {
@@ -113,13 +113,14 @@ class SmallAlloc
 		return smfree(&small_alloc, ptr, size);
 	}
 	static inline void
-	stats(struct alloc_stats *alloc_stats)
+	stats(struct allocator_stats *alloc_stats, mempool_stats_cb cb,
+	      void *cb_ctx)
 	{
 		struct small_stats data_stats;
 		small_stats(&SmallAlloc::small_alloc, &data_stats,
-			    small_stats_noop_cb, NULL);
-		alloc_stats->used = data_stats.used;
-		alloc_stats->total = data_stats.total;
+			    cb, cb_ctx);
+		alloc_stats->small.used = data_stats.used;
+		alloc_stats->small.total = data_stats.total;
 	}
 	static inline struct small_alloc *
 	get_alloc(void)
@@ -154,11 +155,14 @@ class SysAlloc
 		return sysfree(&sys_alloc, ptr, size);
 	}
 	static inline void
-	stats(struct alloc_stats *alloc_stats)
+	stats(struct allocator_stats *alloc_stats, mempool_stats_cb cb,
+	      void *cb_ctx)
 	{
+		(void) cb;
+		(void) cb_ctx;
 		struct sys_stats data_stats;
 		sys_stats(&sys_alloc, &data_stats);
-		alloc_stats->used = data_stats.used;
+		alloc_stats->sys.used = data_stats.used;
 	}
 private:
 	static struct sys_alloc sys_alloc;
@@ -207,3 +211,19 @@ struct allocator_destroy {
 		Allocator::destroy();
 	}
 };
+
+struct allocator_stat {
+	template<typename Allocator, typename...Arg>
+	void
+	invoke(Arg&&...stats)
+	{
+		Allocator::stats(stats...);
+	}
+};
+
+void
+allocators_stats(struct allocator_stats *stats, mempool_stats_cb cb,
+		 void *cb_ctx);
+
+void
+allocators_stats(struct allocator_stats *stats);
\ No newline at end of file
diff --git a/src/box/lua/slab.cc b/src/box/lua/slab.cc
index aa65ff38f9..0df5bb3b36 100644
--- a/src/box/lua/slab.cc
+++ b/src/box/lua/slab.cc
@@ -102,13 +102,14 @@ lbox_slab_stats(struct lua_State *L)
 	struct memtx_engine *memtx;
 	memtx = (struct memtx_engine *)engine_by_name("memtx");
 
-	struct small_stats totals;
+	struct allocator_stats totals;
+	memset(&totals, 0, sizeof(totals));
 	lua_newtable(L);
 	/*
 	 * List all slabs used for tuples and slabs used for
 	 * indexes, with their stats.
 	 */
-	small_stats(SmallAlloc::get_alloc(), &totals, small_stats_lua_cb, L);
+	SmallAlloc::stats(&totals, small_stats_lua_cb, L);
 	struct mempool_stats index_stats;
 	mempool_stats(&memtx->index_extent_pool, &index_stats);
 	small_stats_lua_cb(&index_stats, L);
@@ -122,34 +123,35 @@ lbox_slab_info(struct lua_State *L)
 	struct memtx_engine *memtx;
 	memtx = (struct memtx_engine *)engine_by_name("memtx");
 
-	struct small_stats totals;
+	struct allocator_stats stats;
+	memset(&stats, 0, sizeof(stats));
 
 	/*
 	 * List all slabs used for tuples and slabs used for
 	 * indexes, with their stats.
 	 */
 	lua_newtable(L);
-	small_stats(SmallAlloc::get_alloc(), &totals, small_stats_noop_cb, L);
+	allocators_stats(&stats);
 	struct mempool_stats index_stats;
 	mempool_stats(&memtx->index_extent_pool, &index_stats);
 
 	double ratio;
 	char ratio_buf[32];
 
-	ratio = 100 * ((double) totals.used
-		/ ((double) totals.total + 0.0001));
+	ratio = 100 * ((double) (stats.small.used + stats.sys.used)
+		/ ((double) (stats.small.total + stats.sys.total) + 0.0001));
 	snprintf(ratio_buf, sizeof(ratio_buf), "%0.2lf%%", ratio);
 
 	/** How much address space has been already touched */
 	lua_pushstring(L, "items_size");
-	luaL_pushuint64(L, totals.total);
+	luaL_pushuint64(L, stats.small.total + stats.sys.total);
 	lua_settable(L, -3);
 	/**
 	 * How much of this formatted address space is used for
 	 * actual data.
 	 */
 	lua_pushstring(L, "items_used");
-	luaL_pushuint64(L, totals.used);
+	luaL_pushuint64(L, stats.small.used + stats.sys.used);
 	lua_settable(L, -3);
 
 	/*
@@ -181,10 +183,11 @@ lbox_slab_info(struct lua_State *L)
 	 * data (tuples and indexes).
 	 */
 	lua_pushstring(L, "arena_used");
-	luaL_pushuint64(L, totals.used + index_stats.totals.used);
+	/** System allocator does not use arena. */
+	luaL_pushuint64(L, stats.small.used + index_stats.totals.used);
 	lua_settable(L, -3);
 
-	ratio = 100 * ((double) (totals.used + index_stats.totals.used)
+	ratio = 100 * ((double) (stats.small.used + index_stats.totals.used)
 		       / (double) arena_size);
 	snprintf(ratio_buf, sizeof(ratio_buf), "%0.1lf%%", ratio);
 
diff --git a/src/box/memtx_engine.cc b/src/box/memtx_engine.cc
index cf32e86f94..de918c3353 100644
--- a/src/box/memtx_engine.cc
+++ b/src/box/memtx_engine.cc
@@ -1018,16 +1018,14 @@ static void
 memtx_engine_memory_stat(struct engine *engine, struct engine_memory_stat *stat)
 {
 	struct memtx_engine *memtx = (struct memtx_engine *)engine;
-	struct alloc_stats data_stats;
+	struct allocator_stats data_stats;
 	struct mempool_stats index_stats;
 	mempool_stats(&memtx->index_extent_pool, &index_stats);
 	memset(&data_stats, 0, sizeof(data_stats));
-	SmallAlloc::stats(&data_stats);
-	stat->data += data_stats.used;
+	allocators_stats(&data_stats);
+	stat->data += data_stats.small.used;
+	stat->data += data_stats.sys.used;
 	stat->index += index_stats.totals.used;
-	memset(&data_stats, 0, sizeof(data_stats));
-	SysAlloc::stats(&data_stats);
-	stat->data += data_stats.used;
 }
 
 static const struct engine_vtab memtx_engine_vtab = {
-- 
GitLab