v31-0010-Radix-tree-optionally-tracks-memory-usage-when-R.patch
application/octet-stream
Filename: v31-0010-Radix-tree-optionally-tracks-memory-usage-when-R.patch
Type: application/octet-stream
Part: 12
Patch
Format: format-patch
Series: patch v31-0010
Subject: Radix tree optionally tracks memory usage, when RT_MEASURE_MEMORY_USAGE.
| File | + | − |
|---|---|---|
| contrib/bench_radix_tree/bench_radix_tree.c | 1 | 0 |
| src/backend/utils/mmgr/dsa.c | 0 | 12 |
| src/include/lib/radixtree.h | 83 | 10 |
| src/include/utils/dsa.h | 0 | 1 |
| src/test/modules/test_radixtree/test_radixtree.c | 1 | 0 |
From 7da5e7808ba51aed7ad22b9758b3200cbfcd7d19 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Wed, 8 Mar 2023 15:08:19 +0900
Subject: [PATCH v31 10/14] Radix tree optionally tracks memory usage, when
RT_MEASURE_MEMORY_USAGE.
---
contrib/bench_radix_tree/bench_radix_tree.c | 1 +
src/backend/utils/mmgr/dsa.c | 12 ---
src/include/lib/radixtree.h | 93 +++++++++++++++++--
src/include/utils/dsa.h | 1 -
.../modules/test_radixtree/test_radixtree.c | 1 +
5 files changed, 85 insertions(+), 23 deletions(-)
diff --git a/contrib/bench_radix_tree/bench_radix_tree.c b/contrib/bench_radix_tree/bench_radix_tree.c
index 6e5149e2c4..8a0c754a2c 100644
--- a/contrib/bench_radix_tree/bench_radix_tree.c
+++ b/contrib/bench_radix_tree/bench_radix_tree.c
@@ -34,6 +34,7 @@ PG_MODULE_MAGIC;
#define RT_DECLARE
#define RT_DEFINE
#define RT_USE_DELETE
+#define RT_MEASURE_MEMORY_USAGE
#define RT_VALUE_TYPE uint64
// WIP: compiles with warnings because rt_attach is defined but not used
// #define RT_SHMEM
diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c
index 80555aefff..f5a62061a3 100644
--- a/src/backend/utils/mmgr/dsa.c
+++ b/src/backend/utils/mmgr/dsa.c
@@ -1024,18 +1024,6 @@ dsa_set_size_limit(dsa_area *area, size_t limit)
LWLockRelease(DSA_AREA_LOCK(area));
}
-size_t
-dsa_get_total_size(dsa_area *area)
-{
- size_t size;
-
- LWLockAcquire(DSA_AREA_LOCK(area), LW_SHARED);
- size = area->control->total_segment_size;
- LWLockRelease(DSA_AREA_LOCK(area));
-
- return size;
-}
-
/*
* Aggressively free all spare memory in the hope of returning DSM segments to
* the operating system.
diff --git a/src/include/lib/radixtree.h b/src/include/lib/radixtree.h
index 8bea606c62..f7812eb12a 100644
--- a/src/include/lib/radixtree.h
+++ b/src/include/lib/radixtree.h
@@ -84,7 +84,6 @@
* RT_BEGIN_ITERATE - Begin iterating through all key-value pairs
* RT_ITERATE_NEXT - Return next key-value pair, if any
* RT_END_ITERATE - End iteration
- * RT_MEMORY_USAGE - Get the memory usage
*
* Interface for Shared Memory
* ---------
@@ -97,6 +96,8 @@
* ---------
*
* RT_DELETE - Delete a key-value pair. Declared/define if RT_USE_DELETE is defined
+ * RT_MEMORY_USAGE - Get the memory usage. Declared/define if
+ * RT_MEASURE_MEMORY_USAGE is defined.
*
*
* Copyright (c) 2023, PostgreSQL Global Development Group
@@ -138,7 +139,9 @@
#ifdef RT_USE_DELETE
#define RT_DELETE RT_MAKE_NAME(delete)
#endif
+#ifdef RT_MEASURE_MEMORY_USAGE
#define RT_MEMORY_USAGE RT_MAKE_NAME(memory_usage)
+#endif
#ifdef RT_DEBUG
#define RT_DUMP RT_MAKE_NAME(dump)
#define RT_DUMP_NODE RT_MAKE_NAME(dump_node)
@@ -150,6 +153,9 @@
#define RT_NEW_ROOT RT_MAKE_NAME(new_root)
#define RT_ALLOC_NODE RT_MAKE_NAME(alloc_node)
#define RT_INIT_NODE RT_MAKE_NAME(init_node)
+#ifdef RT_MEASURE_MEMORY_USAGE
+#define RT_FANOUT_GET_NODE_SIZE RT_MAKE_NAME(fanout_get_node_size)
+#endif
#define RT_FREE_NODE RT_MAKE_NAME(free_node)
#define RT_FREE_RECURSE RT_MAKE_NAME(free_recurse)
#define RT_EXTEND_UP RT_MAKE_NAME(extend_up)
@@ -255,7 +261,9 @@ RT_SCOPE RT_ITER * RT_BEGIN_ITERATE(RT_RADIX_TREE *tree);
RT_SCOPE bool RT_ITERATE_NEXT(RT_ITER *iter, uint64 *key_p, RT_VALUE_TYPE *value_p);
RT_SCOPE void RT_END_ITERATE(RT_ITER *iter);
+#ifdef RT_MEASURE_MEMORY_USAGE
RT_SCOPE uint64 RT_MEMORY_USAGE(RT_RADIX_TREE *tree);
+#endif
#ifdef RT_DEBUG
RT_SCOPE void RT_DUMP(RT_RADIX_TREE *tree);
@@ -624,6 +632,10 @@ typedef struct RT_RADIX_TREE_CONTROL
uint64 max_val;
uint64 num_keys;
+#ifdef RT_MEASURE_MEMORY_USAGE
+ int64 mem_used;
+#endif
+
/* statistics */
#ifdef RT_DEBUG
int32 cnt[RT_SIZE_CLASS_COUNT];
@@ -1089,6 +1101,11 @@ RT_ALLOC_NODE(RT_RADIX_TREE *tree, RT_SIZE_CLASS size_class, bool is_leaf)
allocsize);
#endif
+#ifdef RT_MEASURE_MEMORY_USAGE
+ /* update memory usage */
+ tree->ctl->mem_used += allocsize;
+#endif
+
#ifdef RT_DEBUG
/* update the statistics */
tree->ctl->cnt[size_class]++;
@@ -1165,6 +1182,54 @@ RT_SWITCH_NODE_KIND(RT_RADIX_TREE *tree, RT_PTR_ALLOC allocnode, RT_PTR_LOCAL no
return newnode;
}
+#ifdef RT_MEASURE_MEMORY_USAGE
+/* Return the node size of the given fanout of the size class */
+static inline Size
+RT_FANOUT_GET_NODE_SIZE(int fanout, bool is_leaf)
+{
+ const Size fanout_inner_node_size[] = {
+ [3] = RT_SIZE_CLASS_INFO[RT_CLASS_3].inner_size,
+ [15] = RT_SIZE_CLASS_INFO[RT_CLASS_32_MIN].inner_size,
+ [32] = RT_SIZE_CLASS_INFO[RT_CLASS_32_MAX].inner_size,
+ [125] = RT_SIZE_CLASS_INFO[RT_CLASS_125].inner_size,
+ [256] = RT_SIZE_CLASS_INFO[RT_CLASS_256].inner_size,
+ };
+ const Size fanout_leaf_node_size[] = {
+ [3] = RT_SIZE_CLASS_INFO[RT_CLASS_3].leaf_size,
+ [15] = RT_SIZE_CLASS_INFO[RT_CLASS_32_MIN].leaf_size,
+ [32] = RT_SIZE_CLASS_INFO[RT_CLASS_32_MAX].leaf_size,
+ [125] = RT_SIZE_CLASS_INFO[RT_CLASS_125].leaf_size,
+ [256] = RT_SIZE_CLASS_INFO[RT_CLASS_256].leaf_size,
+ };
+ Size node_size;
+
+ node_size = is_leaf ?
+ fanout_leaf_node_size[fanout] : fanout_inner_node_size[fanout];
+
+#ifdef USE_ASSERT_CHECKING
+ {
+ Size assert_node_size = 0;
+
+ for (int i = 0; i < RT_SIZE_CLASS_COUNT; i++)
+ {
+ RT_SIZE_CLASS_ELEM size_class = RT_SIZE_CLASS_INFO[i];
+
+ if (size_class.fanout == fanout)
+ {
+ assert_node_size = is_leaf ?
+ size_class.leaf_size : size_class.inner_size;
+ break;
+ }
+ }
+
+ Assert(node_size == assert_node_size);
+ }
+#endif
+
+ return node_size;
+}
+#endif
+
/* Free the given node */
static void
RT_FREE_NODE(RT_RADIX_TREE *tree, RT_PTR_ALLOC allocnode)
@@ -1197,11 +1262,22 @@ RT_FREE_NODE(RT_RADIX_TREE *tree, RT_PTR_ALLOC allocnode)
}
#endif
+#ifdef RT_MEASURE_MEMORY_USAGE
+ /* update memory usage */
+ {
+ RT_PTR_LOCAL node = RT_PTR_GET_LOCAL(tree, allocnode);
+ tree->ctl->mem_used -= RT_FANOUT_GET_NODE_SIZE(node->fanout,
+ RT_NODE_IS_LEAF(node));
+ Assert(tree->ctl->mem_used >= 0);
+ }
+#endif
+
#ifdef RT_SHMEM
dsa_free(tree->dsa, allocnode);
#else
pfree(allocnode);
#endif
+
}
/* Update the parent's pointer when growing a node */
@@ -1989,27 +2065,23 @@ RT_END_ITERATE(RT_ITER *iter)
/*
* Return the statistics of the amount of memory used by the radix tree.
*/
+#ifdef RT_MEASURE_MEMORY_USAGE
RT_SCOPE uint64
RT_MEMORY_USAGE(RT_RADIX_TREE *tree)
{
Size total = 0;
- RT_LOCK_SHARED(tree);
-
#ifdef RT_SHMEM
Assert(tree->ctl->magic == RT_RADIX_TREE_MAGIC);
- total = dsa_get_total_size(tree->dsa);
-#else
- for (int i = 0; i < RT_SIZE_CLASS_COUNT; i++)
- {
- total += MemoryContextMemAllocated(tree->inner_slabs[i], true);
- total += MemoryContextMemAllocated(tree->leaf_slabs[i], true);
- }
#endif
+ RT_LOCK_SHARED(tree);
+ total = tree->ctl->mem_used;
RT_UNLOCK(tree);
+
return total;
}
+#endif
/*
* Verify the radix tree node.
@@ -2476,6 +2548,7 @@ RT_DUMP(RT_RADIX_TREE *tree)
#undef RT_NEW_ROOT
#undef RT_ALLOC_NODE
#undef RT_INIT_NODE
+#undef RT_FANOUT_GET_NODE_SIZE
#undef RT_FREE_NODE
#undef RT_FREE_RECURSE
#undef RT_EXTEND_UP
diff --git a/src/include/utils/dsa.h b/src/include/utils/dsa.h
index 2af215484f..3ce4ee300a 100644
--- a/src/include/utils/dsa.h
+++ b/src/include/utils/dsa.h
@@ -121,7 +121,6 @@ extern dsa_handle dsa_get_handle(dsa_area *area);
extern dsa_pointer dsa_allocate_extended(dsa_area *area, size_t size, int flags);
extern void dsa_free(dsa_area *area, dsa_pointer dp);
extern void *dsa_get_address(dsa_area *area, dsa_pointer dp);
-extern size_t dsa_get_total_size(dsa_area *area);
extern void dsa_trim(dsa_area *area);
extern void dsa_dump(dsa_area *area);
diff --git a/src/test/modules/test_radixtree/test_radixtree.c b/src/test/modules/test_radixtree/test_radixtree.c
index 5a169854d9..19d286d84b 100644
--- a/src/test/modules/test_radixtree/test_radixtree.c
+++ b/src/test/modules/test_radixtree/test_radixtree.c
@@ -114,6 +114,7 @@ static const test_spec test_specs[] = {
#define RT_DECLARE
#define RT_DEFINE
#define RT_USE_DELETE
+#define RT_MEASURE_MEMORY_USAGE
#define RT_VALUE_TYPE TestValueType
/* #define RT_SHMEM */
#include "lib/radixtree.h"
--
2.31.1