Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 8aa02b5

Browse files
committed
Add ExecStorePinnedBufferHeapTuple.
This allows to avoid an unnecessary pin/unpin cycle when storing a tuple in an already pinned buffer into a slot, when the pin isn't further needed at the call site. Only a single caller for now (to ensure coverage), but upcoming patches will increase use of the new function. Author: Andres Freund Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
1 parent f4b6341 commit 8aa02b5

File tree

3 files changed

+60
-19
lines changed

3 files changed

+60
-19
lines changed

src/backend/executor/execTuples.c

+52-7
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ static TupleDesc ExecTypeFromTLInternal(List *targetList,
7474
static pg_attribute_always_inline void
7575
slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
7676
int natts);
77-
static void tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer);
77+
static inline void tts_buffer_heap_store_tuple(TupleTableSlot *slot,
78+
HeapTuple tuple,
79+
Buffer buffer,
80+
bool transfer_pin);
81+
static void tts_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, bool shouldFree);
7882

7983

8084
const TupleTableSlotOps TTSOpsVirtual;
@@ -743,7 +747,9 @@ tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
743747
}
744748
else
745749
{
746-
tts_buffer_heap_store_tuple(dstslot, bsrcslot->base.tuple, bsrcslot->buffer);
750+
tts_buffer_heap_store_tuple(dstslot, bsrcslot->base.tuple,
751+
bsrcslot->buffer, false);
752+
747753
/*
748754
* Need to materialize because the HeapTupleData portion of the tuple
749755
* might be in a foreign memory context. That's annoying, but until
@@ -792,8 +798,9 @@ tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot)
792798
return minimal_tuple_from_heap_tuple(bslot->base.tuple);
793799
}
794800

795-
static void
796-
tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer)
801+
static inline void
802+
tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple,
803+
Buffer buffer, bool transfer_pin)
797804
{
798805
BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
799806

@@ -813,7 +820,9 @@ tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer
813820

814821
/*
815822
* If tuple is on a disk page, keep the page pinned as long as we hold a
816-
* pointer into it. We assume the caller already has such a pin.
823+
* pointer into it. We assume the caller already has such a pin. If
824+
* transfer_pin is true, we'll transfer that pin to this slot, if not
825+
* we'll pin it again ourselves.
817826
*
818827
* This is coded to optimize the case where the slot previously held a
819828
* tuple on the same disk page: in that case releasing and re-acquiring
@@ -824,8 +833,19 @@ tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer
824833
{
825834
if (BufferIsValid(bslot->buffer))
826835
ReleaseBuffer(bslot->buffer);
836+
827837
bslot->buffer = buffer;
828-
IncrBufferRefCount(buffer);
838+
839+
if (!transfer_pin && BufferIsValid(buffer))
840+
IncrBufferRefCount(buffer);
841+
}
842+
else if (transfer_pin && BufferIsValid(buffer))
843+
{
844+
/*
845+
* In transfer_pin mode the caller won't know about the same-page
846+
* optimization, so we gotta release its pin.
847+
*/
848+
ReleaseBuffer(buffer);
829849
}
830850
}
831851

@@ -1321,7 +1341,32 @@ ExecStoreBufferHeapTuple(HeapTuple tuple,
13211341

13221342
if (unlikely(!TTS_IS_BUFFERTUPLE(slot)))
13231343
elog(ERROR, "trying to store an on-disk heap tuple into wrong type of slot");
1324-
tts_buffer_heap_store_tuple(slot, tuple, buffer);
1344+
tts_buffer_heap_store_tuple(slot, tuple, buffer, false);
1345+
1346+
1347+
return slot;
1348+
}
1349+
1350+
/*
1351+
* Like ExecStoreBufferHeapTuple, but transfer an existing pin from the caller
1352+
* to the slot, i.e. the caller doesn't need to, and may not, release the pin.
1353+
*/
1354+
TupleTableSlot *
1355+
ExecStorePinnedBufferHeapTuple(HeapTuple tuple,
1356+
TupleTableSlot *slot,
1357+
Buffer buffer)
1358+
{
1359+
/*
1360+
* sanity checks
1361+
*/
1362+
Assert(tuple != NULL);
1363+
Assert(slot != NULL);
1364+
Assert(slot->tts_tupleDescriptor != NULL);
1365+
Assert(BufferIsValid(buffer));
1366+
1367+
if (unlikely(!TTS_IS_BUFFERTUPLE(slot)))
1368+
elog(ERROR, "trying to store an on-disk heap tuple into wrong type of slot");
1369+
tts_buffer_heap_store_tuple(slot, tuple, buffer, true);
13251370

13261371
return slot;
13271372
}

src/backend/executor/nodeTidscan.c

+5-12
Original file line numberDiff line numberDiff line change
@@ -379,19 +379,12 @@ TidNext(TidScanState *node)
379379
{
380380
/*
381381
* Store the scanned tuple in the scan tuple slot of the scan
382-
* state. Eventually we will only do this and not return a tuple.
382+
* state, transferring the pin to the slot.
383383
*/
384-
ExecStoreBufferHeapTuple(tuple, /* tuple to store */
385-
slot, /* slot to store in */
386-
buffer); /* buffer associated with
387-
* tuple */
388-
389-
/*
390-
* At this point we have an extra pin on the buffer, because
391-
* ExecStoreHeapTuple incremented the pin count. Drop our local
392-
* pin.
393-
*/
394-
ReleaseBuffer(buffer);
384+
ExecStorePinnedBufferHeapTuple(tuple, /* tuple to store */
385+
slot, /* slot to store in */
386+
buffer); /* buffer associated with
387+
* tuple */
395388

396389
return slot;
397390
}

src/include/executor/tuptable.h

+3
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,9 @@ extern void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot);
305305
extern TupleTableSlot *ExecStoreBufferHeapTuple(HeapTuple tuple,
306306
TupleTableSlot *slot,
307307
Buffer buffer);
308+
extern TupleTableSlot *ExecStorePinnedBufferHeapTuple(HeapTuple tuple,
309+
TupleTableSlot *slot,
310+
Buffer buffer);
308311
extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup,
309312
TupleTableSlot *slot,
310313
bool shouldFree);

0 commit comments

Comments
 (0)