v16-0009-Use-bitmap-operations-for-isset-arrays-rather-th.patch
text/x-patch
Filename: v16-0009-Use-bitmap-operations-for-isset-arrays-rather-th.patch
Type: text/x-patch
Part: 5
Patch
Format: format-patch
Series: patch v16-0009
Subject: Use bitmap operations for isset arrays rather than byte operations
| File | + | − |
|---|---|---|
| src/backend/lib/radixtree.c | 36 | 28 |
From e1085a0420f719f7e4ce8a904794ab8e484b75a9 Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Mon, 19 Dec 2022 16:16:12 +0700
Subject: [PATCH v16 09/12] Use bitmap operations for isset arrays rather than
byte operations
It's simpler to do the same thing everywhere, even for node256
where iteration performance doesn't matter as much because we
always can insert directly.
Also rename WORDNUM and BITNUM to avoid clashing with bitmapset.c.
---
src/backend/lib/radixtree.c | 64 +++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 28 deletions(-)
diff --git a/src/backend/lib/radixtree.c b/src/backend/lib/radixtree.c
index ddf7b002fc..7899e844fb 100644
--- a/src/backend/lib/radixtree.c
+++ b/src/backend/lib/radixtree.c
@@ -77,12 +77,6 @@
/* The number of maximum slots in the node */
#define RT_NODE_MAX_SLOTS (1 << RT_NODE_SPAN)
-/*
- * Return the number of bits required to represent nslots slots, used
- * nodes indexed by array lookup.
- */
-#define RT_NODE_NSLOTS_BITS(nslots) ((nslots) / (sizeof(uint8) * BITS_PER_BYTE))
-
/* Mask for extracting a chunk from the key */
#define RT_CHUNK_MASK ((1 << RT_NODE_SPAN) - 1)
@@ -98,15 +92,9 @@
/* Get a chunk from the key */
#define RT_GET_KEY_CHUNK(key, shift) ((uint8) (((key) >> (shift)) & RT_CHUNK_MASK))
-/*
- * Mapping from the value to the bit in is-set bitmap in the node-256.
- */
-#define RT_NODE_BITMAP_BYTE(v) ((v) / BITS_PER_BYTE)
-#define RT_NODE_BITMAP_BIT(v) (UINT64CONST(1) << ((v) % RT_NODE_SPAN))
-
-/* FIXME rename */
-#define WORDNUM(x) ((x) / BITS_PER_BITMAPWORD)
-#define BITNUM(x) ((x) % BITS_PER_BITMAPWORD)
+/* For accessing bitmaps */
+#define BM_IDX(x) ((x) / BITS_PER_BITMAPWORD)
+#define BM_BIT(x) ((x) % BITS_PER_BITMAPWORD)
/* Enum used rt_node_search() */
typedef enum
@@ -214,7 +202,7 @@ typedef struct rt_node_base125
uint8 slot_idxs[RT_NODE_MAX_SLOTS];
/* isset is a bitmap to track which slot is in use */
- bitmapword isset[WORDNUM(128)];
+ bitmapword isset[BM_IDX(128)];
} rt_node_base_125;
typedef struct rt_node_base256
@@ -300,7 +288,7 @@ typedef struct rt_node_leaf_256
rt_node_base_256 base;
/* isset is a bitmap to track which slot is in use */
- uint8 isset[RT_NODE_NSLOTS_BITS(RT_NODE_MAX_SLOTS)];
+ bitmapword isset[BM_IDX(RT_NODE_MAX_SLOTS)];
/* Slots for 256 values */
uint64 values[RT_NODE_MAX_SLOTS];
@@ -665,17 +653,23 @@ node_125_is_chunk_used(rt_node_base_125 *node, uint8 chunk)
static inline bool
node_inner_125_is_slot_used(rt_node_inner_125 *node, uint8 slot)
{
+ int idx = BM_IDX(slot);
+ int bitnum = BM_BIT(slot);
+
Assert(!NODE_IS_LEAF(node));
Assert(slot < node->base.n.fanout);
- return (node->base.isset[WORDNUM(slot)] & ((bitmapword) 1 << BITNUM(slot))) != 0;
+ return (node->base.isset[idx] & ((bitmapword) 1 << bitnum)) != 0;
}
static inline bool
node_leaf_125_is_slot_used(rt_node_leaf_125 *node, uint8 slot)
{
+ int idx = BM_IDX(slot);
+ int bitnum = BM_BIT(slot);
+
Assert(NODE_IS_LEAF(node));
Assert(slot < node->base.n.fanout);
- return (node->base.isset[WORDNUM(slot)] & ((bitmapword) 1 << BITNUM(slot))) != 0;
+ return (node->base.isset[idx] & ((bitmapword) 1 << bitnum)) != 0;
}
#endif
@@ -698,9 +692,12 @@ static void
node_inner_125_delete(rt_node_inner_125 *node, uint8 chunk)
{
int slotpos = node->base.slot_idxs[chunk];
+ int idx = BM_IDX(slotpos);
+ int bitnum = BM_BIT(slotpos);
Assert(!NODE_IS_LEAF(node));
- node->base.isset[WORDNUM(slotpos)] &= ~((bitmapword) 1 << BITNUM(slotpos));
+
+ node->base.isset[idx] &= ~((bitmapword) 1 << bitnum);
node->children[node->base.slot_idxs[chunk]] = NULL;
node->base.slot_idxs[chunk] = RT_NODE_125_INVALID_IDX;
}
@@ -709,9 +706,11 @@ static void
node_leaf_125_delete(rt_node_leaf_125 *node, uint8 chunk)
{
int slotpos = node->base.slot_idxs[chunk];
+ int idx = BM_IDX(slotpos);
+ int bitnum = BM_BIT(slotpos);
Assert(NODE_IS_LEAF(node));
- node->base.isset[WORDNUM(slotpos)] &= ~((bitmapword) 1 << BITNUM(slotpos));
+ node->base.isset[idx] &= ~((bitmapword) 1 << bitnum);
node->base.slot_idxs[chunk] = RT_NODE_125_INVALID_IDX;
}
@@ -724,7 +723,7 @@ node_125_find_unused_slot(bitmapword *isset)
bitmapword inverse;
/* get the first word with at least one bit not set */
- for (idx = 0; idx < WORDNUM(128); idx++)
+ for (idx = 0; idx < BM_IDX(128); idx++)
{
if (isset[idx] < ~((bitmapword) 0))
break;
@@ -798,8 +797,11 @@ node_inner_256_is_chunk_used(rt_node_inner_256 *node, uint8 chunk)
static inline bool
node_leaf_256_is_chunk_used(rt_node_leaf_256 *node, uint8 chunk)
{
+ int idx = BM_IDX(chunk);
+ int bitnum = BM_BIT(chunk);
+
Assert(NODE_IS_LEAF(node));
- return (node->isset[RT_NODE_BITMAP_BYTE(chunk)] & RT_NODE_BITMAP_BIT(chunk)) != 0;
+ return (node->isset[idx] & ((bitmapword) 1 << bitnum)) != 0;
}
static inline rt_node *
@@ -830,8 +832,11 @@ node_inner_256_set(rt_node_inner_256 *node, uint8 chunk, rt_node *child)
static inline void
node_leaf_256_set(rt_node_leaf_256 *node, uint8 chunk, uint64 value)
{
+ int idx = BM_IDX(chunk);
+ int bitnum = BM_BIT(chunk);
+
Assert(NODE_IS_LEAF(node));
- node->isset[RT_NODE_BITMAP_BYTE(chunk)] |= RT_NODE_BITMAP_BIT(chunk);
+ node->isset[idx] |= ((bitmapword) 1 << bitnum);
node->values[chunk] = value;
}
@@ -846,8 +851,11 @@ node_inner_256_delete(rt_node_inner_256 *node, uint8 chunk)
static inline void
node_leaf_256_delete(rt_node_leaf_256 *node, uint8 chunk)
{
+ int idx = BM_IDX(chunk);
+ int bitnum = BM_BIT(chunk);
+
Assert(NODE_IS_LEAF(node));
- node->isset[RT_NODE_BITMAP_BYTE(chunk)] &= ~(RT_NODE_BITMAP_BIT(chunk));
+ node->isset[idx] &= ~((bitmapword) 1 << bitnum);
}
/*
@@ -2269,8 +2277,8 @@ rt_verify_node(rt_node *node)
rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node;
int cnt = 0;
- for (int i = 0; i < RT_NODE_NSLOTS_BITS(RT_NODE_MAX_SLOTS); i++)
- cnt += pg_popcount32(n256->isset[i]);
+ for (int i = 0; i < BM_IDX(RT_NODE_MAX_SLOTS); i++)
+ cnt += bmw_popcount(n256->isset[i]);
/* Check if the number of used chunk matches */
Assert(n256->base.n.count == cnt);
@@ -2386,7 +2394,7 @@ rt_dump_node(rt_node *node, int level, bool recurse)
rt_node_leaf_125 *n = (rt_node_leaf_125 *) node;
fprintf(stderr, ", isset-bitmap:");
- for (int i = 0; i < WORDNUM(128); i++)
+ for (int i = 0; i < BM_IDX(128); i++)
{
fprintf(stderr, UINT64_FORMAT_HEX " ", n->base.isset[i]);
}
--
2.38.1