]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Use bump context for TID bitmaps stored by vacuum
authorJohn Naylor <john.naylor@postgresql.org>
Sun, 7 Apr 2024 05:27:34 +0000 (12:27 +0700)
committerJohn Naylor <john.naylor@postgresql.org>
Mon, 8 Apr 2024 07:39:49 +0000 (14:39 +0700)
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

src/backend/access/common/tidstore.c
src/backend/access/heap/vacuumlazy.c
src/include/access/tidstore.h
src/include/lib/radixtree.h
src/test/modules/test_tidstore/test_tidstore.c

index 629390a1f88e02d912e12abeb39ff02ba4778cda..211d63941c2c3185d8f1f736cc09ffc1d29dfd9d 100644 (file)
@@ -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);
 
index c3a9dc1ad6d855d036f0e66cf7e563457d796c2f..de109acc89ae400347eac5040f420ea091121a1e 100644 (file)
@@ -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;
index f05d7487837a757ba6e2f40a7eea6219d093bb32..32aa9995193fa54e26ea31afb1fa7f3d89aaf6be 100644 (file)
@@ -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);
index 6f36e8bfde300e46208b992d8d237b63cf647d7a..6764b58b52a233a9c335f2e69ecc48f62fc49d8e 100644 (file)
@@ -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;
 
index 32c6c477b7256a96471230fda43d418d05a1afea..0a3a58722de8565c8fc93b5cbdfa7e02fa3ab5d0 100644 (file)
@@ -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);