aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Naylor <john.naylor@postgresql.org>2024-04-07 12:27:34 +0700
committerJohn Naylor <john.naylor@postgresql.org>2024-04-08 14:39:49 +0700
commit8a1b31e6e59631807a08a4e9465134c343bbdf5e (patch)
tree72f147d6442438d8ce033c981a90a7b9c43a904c /src
parentbb766cde63b4f624d029b34c9cdd3d0a94fd5b46 (diff)
downloadpostgresql-8a1b31e6e59631807a08a4e9465134c343bbdf5e.tar.gz
postgresql-8a1b31e6e59631807a08a4e9465134c343bbdf5e.zip
Use bump context for TID bitmaps stored by vacuum
Vacuum does not pfree individual entries, and only frees the entire storage space when finished with it. This allows using a bump context, eliminating the chunk header in each leaf allocation. Most leaf allocations will be 16 to 32 bytes, so that's a significant savings. TidStoreCreateLocal gets a boolean parameter to indicate that the created store is insert-only. This requires a separate tree context for iteration, since we free the iteration state after iteration completes. Discussion: https://postgr.es/m/CANWCAZac%3DpBePg3rhX8nXkUuaLoiAJJLtmnCfZsPEAS4EtJ%3Dkg%40mail.gmail.com Discussion: https://postgr.es/m/CANWCAZZQFfxvzO8yZHFWtQV+Z2gAMv1ku16Vu7KWmb5kZQyd1w@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/common/tidstore.c15
-rw-r--r--src/backend/access/heap/vacuumlazy.c4
-rw-r--r--src/include/access/tidstore.h2
-rw-r--r--src/include/lib/radixtree.h11
-rw-r--r--src/test/modules/test_tidstore/test_tidstore.c3
5 files changed, 28 insertions, 7 deletions
diff --git a/src/backend/access/common/tidstore.c b/src/backend/access/common/tidstore.c
index 629390a1f88..211d63941c2 100644
--- a/src/backend/access/common/tidstore.c
+++ b/src/backend/access/common/tidstore.c
@@ -120,7 +120,7 @@ static void tidstore_iter_extract_tids(TidStoreIter *iter, BlockNumber blkno,
* by TidStoreMemoryUsage().
*/
TidStore *
-TidStoreCreateLocal(size_t max_bytes)
+TidStoreCreateLocal(size_t max_bytes, bool insert_only)
{
TidStore *ts;
size_t initBlockSize = ALLOCSET_DEFAULT_INITSIZE;
@@ -138,11 +138,22 @@ TidStoreCreateLocal(size_t max_bytes)
maxBlockSize = ALLOCSET_DEFAULT_INITSIZE;
/* Create a memory context for the TID storage */
- ts->rt_context = AllocSetContextCreate(CurrentMemoryContext,
+ if (insert_only)
+ {
+ ts->rt_context = BumpContextCreate(CurrentMemoryContext,
"TID storage",
minContextSize,
initBlockSize,
maxBlockSize);
+ }
+ else
+ {
+ ts->rt_context = AllocSetContextCreate(CurrentMemoryContext,
+ "TID storage",
+ minContextSize,
+ initBlockSize,
+ maxBlockSize);
+ }
ts->tree.local = local_ts_create(ts->rt_context);
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index c3a9dc1ad6d..de109acc89a 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -2874,7 +2874,7 @@ dead_items_alloc(LVRelState *vacrel, int nworkers)
dead_items_info->num_items = 0;
vacrel->dead_items_info = dead_items_info;
- vacrel->dead_items = TidStoreCreateLocal(dead_items_info->max_bytes);
+ vacrel->dead_items = TidStoreCreateLocal(dead_items_info->max_bytes, true);
}
/*
@@ -2910,7 +2910,7 @@ dead_items_reset(LVRelState *vacrel)
/* Recreate the tidstore with the same max_bytes limitation */
TidStoreDestroy(dead_items);
- vacrel->dead_items = TidStoreCreateLocal(vacrel->dead_items_info->max_bytes);
+ vacrel->dead_items = TidStoreCreateLocal(vacrel->dead_items_info->max_bytes, true);
/* Reset the counter */
vacrel->dead_items_info->num_items = 0;
diff --git a/src/include/access/tidstore.h b/src/include/access/tidstore.h
index f05d7487837..32aa9995193 100644
--- a/src/include/access/tidstore.h
+++ b/src/include/access/tidstore.h
@@ -29,7 +29,7 @@ typedef struct TidStoreIterResult
OffsetNumber *offsets;
} TidStoreIterResult;
-extern TidStore *TidStoreCreateLocal(size_t max_bytes);
+extern TidStore *TidStoreCreateLocal(size_t max_bytes, bool insert_only);
extern TidStore *TidStoreCreateShared(size_t max_bytes, int tranche_id);
extern TidStore *TidStoreAttach(dsa_handle area_handle, dsa_pointer handle);
extern void TidStoreDetach(TidStore *ts);
diff --git a/src/include/lib/radixtree.h b/src/include/lib/radixtree.h
index 6f36e8bfde3..6764b58b52a 100644
--- a/src/include/lib/radixtree.h
+++ b/src/include/lib/radixtree.h
@@ -691,6 +691,7 @@ struct RT_RADIX_TREE
/* leaf_context is used only for single-value leaves */
MemoryContextData *leaf_context;
#endif
+ MemoryContextData *iter_context;
};
/*
@@ -1796,6 +1797,14 @@ RT_CREATE(MemoryContext ctx)
tree = (RT_RADIX_TREE *) palloc0(sizeof(RT_RADIX_TREE));
tree->context = ctx;
+ /*
+ * Separate context for iteration in case the tree context doesn't support
+ * pfree
+ */
+ tree->iter_context = AllocSetContextCreate(ctx,
+ RT_STR(RT_PREFIX) "radix_tree iter context",
+ ALLOCSET_SMALL_SIZES);
+
#ifdef RT_SHMEM
tree->dsa = dsa;
dp = dsa_allocate0(dsa, sizeof(RT_RADIX_TREE_CONTROL));
@@ -2038,7 +2047,7 @@ RT_BEGIN_ITERATE(RT_RADIX_TREE * tree)
RT_ITER *iter;
RT_CHILD_PTR root;
- iter = (RT_ITER *) MemoryContextAllocZero(tree->context,
+ iter = (RT_ITER *) MemoryContextAllocZero(tree->iter_context,
sizeof(RT_ITER));
iter->tree = tree;
diff --git a/src/test/modules/test_tidstore/test_tidstore.c b/src/test/modules/test_tidstore/test_tidstore.c
index 32c6c477b72..0a3a58722de 100644
--- a/src/test/modules/test_tidstore/test_tidstore.c
+++ b/src/test/modules/test_tidstore/test_tidstore.c
@@ -116,7 +116,8 @@ test_create(PG_FUNCTION_ARGS)
dsa_pin_mapping(TidStoreGetDSA(tidstore));
}
else
- tidstore = TidStoreCreateLocal(tidstore_max_size);
+ /* VACUUM uses insert only, so we test the other option. */
+ tidstore = TidStoreCreateLocal(tidstore_max_size, false);
tidstore_empty_size = TidStoreMemoryUsage(tidstore);