diff options
author | Andres Freund <andres@anarazel.de> | 2018-10-15 15:24:33 -0700 |
---|---|---|
committer | Andres Freund <andres@anarazel.de> | 2018-10-15 18:23:25 -0700 |
commit | c5257345ef61922468cd9abd887c3cb6c38792cb (patch) | |
tree | c510b809c925fba6eb0b778b53b2345ea9168e50 /src/backend/executor | |
parent | 9d906f1119de893a4ca533c5e7b97207a3aa963b (diff) | |
download | postgresql-c5257345ef61922468cd9abd887c3cb6c38792cb.tar.gz postgresql-c5257345ef61922468cd9abd887c3cb6c38792cb.zip |
Move TupleTableSlots boolean member into one flag variable.
There's several reasons for this change:
1) It reduces the total size of TupleTableSlot / reduces alignment
padding, making the commonly accessed members fit into a single
cacheline (but we currently do not force proper alignment, so
that's not yet guaranteed to be helpful)
2) Combining the booleans into a flag allows to combine read/writes
from memory.
3) With the upcoming slot abstraction changes, it allows to have core
and extended flags, in a memory efficient way.
Author: Ashutosh Bapat and Andres Freund
Discussion: https://postgr.es/m/20180220224318.gw4oe5jadhpmcdnm@alap3.anarazel.de
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execTuples.c | 96 | ||||
-rw-r--r-- | src/backend/executor/nodeAgg.c | 2 | ||||
-rw-r--r-- | src/backend/executor/nodeModifyTable.c | 2 |
3 files changed, 60 insertions, 40 deletions
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index fbbac1c6bf8..015752a93f1 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -101,11 +101,10 @@ MakeTupleTableSlot(TupleDesc tupleDesc) slot = palloc0(sz); slot->type = T_TupleTableSlot; - slot->tts_isempty = true; - slot->tts_shouldFree = false; - slot->tts_shouldFreeMin = false; + slot->tts_flags |= TTS_FLAG_EMPTY; + if (tupleDesc != NULL) + slot->tts_flags |= TTS_FLAG_FIXED; slot->tts_tuple = NULL; - slot->tts_fixedTupleDescriptor = tupleDesc != NULL; slot->tts_tupleDescriptor = tupleDesc; slot->tts_mcxt = CurrentMemoryContext; slot->tts_buffer = InvalidBuffer; @@ -176,7 +175,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */ /* If shouldFree, release memory occupied by the slot itself */ if (shouldFree) { - if (!slot->tts_fixedTupleDescriptor) + if (!TTS_FIXED(slot)) { if (slot->tts_values) pfree(slot->tts_values); @@ -224,7 +223,7 @@ ExecDropSingleTupleTableSlot(TupleTableSlot *slot) ExecClearTuple(slot); if (slot->tts_tupleDescriptor) ReleaseTupleDesc(slot->tts_tupleDescriptor); - if (!slot->tts_fixedTupleDescriptor) + if (!TTS_FIXED(slot)) { if (slot->tts_values) pfree(slot->tts_values); @@ -254,7 +253,7 @@ void ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */ TupleDesc tupdesc) /* new tuple descriptor */ { - Assert(!slot->tts_fixedTupleDescriptor); + Assert(!TTS_FIXED(slot)); /* For safety, make sure slot is empty before changing it */ ExecClearTuple(slot); @@ -325,17 +324,23 @@ ExecStoreHeapTuple(HeapTuple tuple, /* * Free any old physical tuple belonging to the slot. */ - if (slot->tts_shouldFree) + if (TTS_SHOULDFREE(slot)) + { heap_freetuple(slot->tts_tuple); - if (slot->tts_shouldFreeMin) + slot->tts_flags &= ~TTS_FLAG_SHOULDFREE; + } + if (TTS_SHOULDFREEMIN(slot)) + { heap_free_minimal_tuple(slot->tts_mintuple); + slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN; + } /* * Store the new tuple into the specified slot. */ - slot->tts_isempty = false; - slot->tts_shouldFree = shouldFree; - slot->tts_shouldFreeMin = false; + slot->tts_flags &= ~TTS_FLAG_EMPTY; + if (shouldFree) + slot->tts_flags |= TTS_FLAG_SHOULDFREE; slot->tts_tuple = tuple; slot->tts_mintuple = NULL; @@ -382,17 +387,21 @@ ExecStoreBufferHeapTuple(HeapTuple tuple, /* * Free any old physical tuple belonging to the slot. */ - if (slot->tts_shouldFree) + if (TTS_SHOULDFREE(slot)) + { heap_freetuple(slot->tts_tuple); - if (slot->tts_shouldFreeMin) + slot->tts_flags &= ~TTS_FLAG_SHOULDFREE; + } + if (TTS_SHOULDFREEMIN(slot)) + { heap_free_minimal_tuple(slot->tts_mintuple); + slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN; + } /* * Store the new tuple into the specified slot. */ - slot->tts_isempty = false; - slot->tts_shouldFree = false; - slot->tts_shouldFreeMin = false; + slot->tts_flags &= ~TTS_FLAG_EMPTY; slot->tts_tuple = tuple; slot->tts_mintuple = NULL; @@ -442,10 +451,16 @@ ExecStoreMinimalTuple(MinimalTuple mtup, /* * Free any old physical tuple belonging to the slot. */ - if (slot->tts_shouldFree) + if (TTS_SHOULDFREE(slot)) + { heap_freetuple(slot->tts_tuple); - if (slot->tts_shouldFreeMin) + slot->tts_flags &= ~TTS_FLAG_SHOULDFREE; + } + if (TTS_SHOULDFREEMIN(slot)) + { heap_free_minimal_tuple(slot->tts_mintuple); + slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN; + } /* * Drop the pin on the referenced buffer, if there is one. @@ -458,9 +473,9 @@ ExecStoreMinimalTuple(MinimalTuple mtup, /* * Store the new tuple into the specified slot. */ - slot->tts_isempty = false; - slot->tts_shouldFree = false; - slot->tts_shouldFreeMin = shouldFree; + slot->tts_flags &= ~TTS_FLAG_EMPTY; + if (shouldFree) + slot->tts_flags |= TTS_FLAG_SHOULDFREEMIN; slot->tts_tuple = &slot->tts_minhdr; slot->tts_mintuple = mtup; @@ -493,15 +508,19 @@ ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */ /* * Free the old physical tuple if necessary. */ - if (slot->tts_shouldFree) + if (TTS_SHOULDFREE(slot)) + { heap_freetuple(slot->tts_tuple); - if (slot->tts_shouldFreeMin) + slot->tts_flags &= ~TTS_FLAG_SHOULDFREE; + } + if (TTS_SHOULDFREEMIN(slot)) + { heap_free_minimal_tuple(slot->tts_mintuple); + slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN; + } slot->tts_tuple = NULL; slot->tts_mintuple = NULL; - slot->tts_shouldFree = false; - slot->tts_shouldFreeMin = false; /* * Drop the pin on the referenced buffer, if there is one. @@ -514,7 +533,7 @@ ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */ /* * Mark it empty. */ - slot->tts_isempty = true; + slot->tts_flags |= TTS_FLAG_EMPTY; slot->tts_nvalid = 0; return slot; @@ -539,9 +558,9 @@ ExecStoreVirtualTuple(TupleTableSlot *slot) */ Assert(slot != NULL); Assert(slot->tts_tupleDescriptor != NULL); - Assert(slot->tts_isempty); + Assert(TTS_EMPTY(slot)); - slot->tts_isempty = false; + slot->tts_flags &= ~TTS_FLAG_EMPTY; slot->tts_nvalid = slot->tts_tupleDescriptor->natts; return slot; @@ -595,7 +614,7 @@ ExecCopySlotTuple(TupleTableSlot *slot) * sanity checks */ Assert(slot != NULL); - Assert(!slot->tts_isempty); + Assert(!TTS_EMPTY(slot)); /* * If we have a physical tuple (either format) then just copy it. @@ -627,7 +646,7 @@ ExecCopySlotMinimalTuple(TupleTableSlot *slot) * sanity checks */ Assert(slot != NULL); - Assert(!slot->tts_isempty); + Assert(!TTS_EMPTY(slot)); /* * If we have a physical tuple then just copy it. Prefer to copy @@ -675,7 +694,7 @@ ExecFetchSlotTuple(TupleTableSlot *slot) * sanity checks */ Assert(slot != NULL); - Assert(!slot->tts_isempty); + Assert(!TTS_EMPTY(slot)); /* * If we have a regular physical tuple then just return it. @@ -724,7 +743,8 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot) * sanity checks */ Assert(slot != NULL); - Assert(!slot->tts_isempty); + Assert(!TTS_EMPTY(slot)); + /* * If we have a minimal physical tuple (local or not) then just return it. @@ -741,7 +761,7 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot) */ oldContext = MemoryContextSwitchTo(slot->tts_mcxt); slot->tts_mintuple = ExecCopySlotMinimalTuple(slot); - slot->tts_shouldFreeMin = true; + slot->tts_flags |= TTS_FLAG_SHOULDFREEMIN; MemoryContextSwitchTo(oldContext); /* @@ -797,13 +817,13 @@ ExecMaterializeSlot(TupleTableSlot *slot) * sanity checks */ Assert(slot != NULL); - Assert(!slot->tts_isempty); + Assert(!TTS_EMPTY(slot)); /* * If we have a regular physical tuple, and it's locally palloc'd, we have * nothing to do. */ - if (slot->tts_tuple && slot->tts_shouldFree) + if (slot->tts_tuple && TTS_SHOULDFREE(slot)) return slot->tts_tuple; /* @@ -815,7 +835,7 @@ ExecMaterializeSlot(TupleTableSlot *slot) */ oldContext = MemoryContextSwitchTo(slot->tts_mcxt); slot->tts_tuple = ExecCopySlotTuple(slot); - slot->tts_shouldFree = true; + slot->tts_flags |= TTS_FLAG_SHOULDFREE; MemoryContextSwitchTo(oldContext); /* @@ -842,7 +862,7 @@ ExecMaterializeSlot(TupleTableSlot *slot) * storage, we must not pfree it now, since callers might have already * fetched datum pointers referencing it.) */ - if (!slot->tts_shouldFreeMin) + if (!TTS_SHOULDFREEMIN(slot)) slot->tts_mintuple = NULL; return slot->tts_tuple; diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 98d8483b720..2413f1f87db 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -1080,7 +1080,7 @@ prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet aggstate->grouped_cols = grouped_cols; - if (slot->tts_isempty) + if (TTS_EMPTY(slot)) { /* * Force all values to be NULL if working on an empty input tuple diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 24beb40435e..528f58717e2 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -699,7 +699,7 @@ ExecDelete(ModifyTableState *mtstate, * RETURNING expressions might reference the tableoid column, so * initialize t_tableOid before evaluating them. */ - if (slot->tts_isempty) + if (TTS_EMPTY(slot)) ExecStoreAllNullTuple(slot); tuple = ExecMaterializeSlot(slot); tuple->t_tableOid = RelationGetRelid(resultRelationDesc); |