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
This commit is contained in:
parent
bb766cde63
commit
8a1b31e6e5
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue