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

Commit c525734

Browse files
committed
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
1 parent 9d906f1 commit c525734

File tree

8 files changed

+116
-72
lines changed

8 files changed

+116
-72
lines changed

src/backend/access/common/heaptuple.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -1391,7 +1391,7 @@ slot_deform_tuple(TupleTableSlot *slot, int natts)
13911391
{
13921392
/* Restore state from previous execution */
13931393
off = slot->tts_off;
1394-
slow = slot->tts_slow;
1394+
slow = TTS_SLOW(slot);
13951395
}
13961396

13971397
tp = (char *) tup + tup->t_hoff;
@@ -1452,7 +1452,10 @@ slot_deform_tuple(TupleTableSlot *slot, int natts)
14521452
*/
14531453
slot->tts_nvalid = attnum;
14541454
slot->tts_off = off;
1455-
slot->tts_slow = slow;
1455+
if (slow)
1456+
slot->tts_flags |= TTS_FLAG_SLOW;
1457+
else
1458+
slot->tts_flags &= ~TTS_FLAG_SLOW;
14561459
}
14571460

14581461
/*

src/backend/executor/execTuples.c

+58-38
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,10 @@ MakeTupleTableSlot(TupleDesc tupleDesc)
101101

102102
slot = palloc0(sz);
103103
slot->type = T_TupleTableSlot;
104-
slot->tts_isempty = true;
105-
slot->tts_shouldFree = false;
106-
slot->tts_shouldFreeMin = false;
104+
slot->tts_flags |= TTS_FLAG_EMPTY;
105+
if (tupleDesc != NULL)
106+
slot->tts_flags |= TTS_FLAG_FIXED;
107107
slot->tts_tuple = NULL;
108-
slot->tts_fixedTupleDescriptor = tupleDesc != NULL;
109108
slot->tts_tupleDescriptor = tupleDesc;
110109
slot->tts_mcxt = CurrentMemoryContext;
111110
slot->tts_buffer = InvalidBuffer;
@@ -176,7 +175,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
176175
/* If shouldFree, release memory occupied by the slot itself */
177176
if (shouldFree)
178177
{
179-
if (!slot->tts_fixedTupleDescriptor)
178+
if (!TTS_FIXED(slot))
180179
{
181180
if (slot->tts_values)
182181
pfree(slot->tts_values);
@@ -224,7 +223,7 @@ ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
224223
ExecClearTuple(slot);
225224
if (slot->tts_tupleDescriptor)
226225
ReleaseTupleDesc(slot->tts_tupleDescriptor);
227-
if (!slot->tts_fixedTupleDescriptor)
226+
if (!TTS_FIXED(slot))
228227
{
229228
if (slot->tts_values)
230229
pfree(slot->tts_values);
@@ -254,7 +253,7 @@ void
254253
ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
255254
TupleDesc tupdesc) /* new tuple descriptor */
256255
{
257-
Assert(!slot->tts_fixedTupleDescriptor);
256+
Assert(!TTS_FIXED(slot));
258257

259258
/* For safety, make sure slot is empty before changing it */
260259
ExecClearTuple(slot);
@@ -325,17 +324,23 @@ ExecStoreHeapTuple(HeapTuple tuple,
325324
/*
326325
* Free any old physical tuple belonging to the slot.
327326
*/
328-
if (slot->tts_shouldFree)
327+
if (TTS_SHOULDFREE(slot))
328+
{
329329
heap_freetuple(slot->tts_tuple);
330-
if (slot->tts_shouldFreeMin)
330+
slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
331+
}
332+
if (TTS_SHOULDFREEMIN(slot))
333+
{
331334
heap_free_minimal_tuple(slot->tts_mintuple);
335+
slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
336+
}
332337

333338
/*
334339
* Store the new tuple into the specified slot.
335340
*/
336-
slot->tts_isempty = false;
337-
slot->tts_shouldFree = shouldFree;
338-
slot->tts_shouldFreeMin = false;
341+
slot->tts_flags &= ~TTS_FLAG_EMPTY;
342+
if (shouldFree)
343+
slot->tts_flags |= TTS_FLAG_SHOULDFREE;
339344
slot->tts_tuple = tuple;
340345
slot->tts_mintuple = NULL;
341346

@@ -382,17 +387,21 @@ ExecStoreBufferHeapTuple(HeapTuple tuple,
382387
/*
383388
* Free any old physical tuple belonging to the slot.
384389
*/
385-
if (slot->tts_shouldFree)
390+
if (TTS_SHOULDFREE(slot))
391+
{
386392
heap_freetuple(slot->tts_tuple);
387-
if (slot->tts_shouldFreeMin)
393+
slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
394+
}
395+
if (TTS_SHOULDFREEMIN(slot))
396+
{
388397
heap_free_minimal_tuple(slot->tts_mintuple);
398+
slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
399+
}
389400

390401
/*
391402
* Store the new tuple into the specified slot.
392403
*/
393-
slot->tts_isempty = false;
394-
slot->tts_shouldFree = false;
395-
slot->tts_shouldFreeMin = false;
404+
slot->tts_flags &= ~TTS_FLAG_EMPTY;
396405
slot->tts_tuple = tuple;
397406
slot->tts_mintuple = NULL;
398407

@@ -442,10 +451,16 @@ ExecStoreMinimalTuple(MinimalTuple mtup,
442451
/*
443452
* Free any old physical tuple belonging to the slot.
444453
*/
445-
if (slot->tts_shouldFree)
454+
if (TTS_SHOULDFREE(slot))
455+
{
446456
heap_freetuple(slot->tts_tuple);
447-
if (slot->tts_shouldFreeMin)
457+
slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
458+
}
459+
if (TTS_SHOULDFREEMIN(slot))
460+
{
448461
heap_free_minimal_tuple(slot->tts_mintuple);
462+
slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
463+
}
449464

450465
/*
451466
* Drop the pin on the referenced buffer, if there is one.
@@ -458,9 +473,9 @@ ExecStoreMinimalTuple(MinimalTuple mtup,
458473
/*
459474
* Store the new tuple into the specified slot.
460475
*/
461-
slot->tts_isempty = false;
462-
slot->tts_shouldFree = false;
463-
slot->tts_shouldFreeMin = shouldFree;
476+
slot->tts_flags &= ~TTS_FLAG_EMPTY;
477+
if (shouldFree)
478+
slot->tts_flags |= TTS_FLAG_SHOULDFREEMIN;
464479
slot->tts_tuple = &slot->tts_minhdr;
465480
slot->tts_mintuple = mtup;
466481

@@ -493,15 +508,19 @@ ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */
493508
/*
494509
* Free the old physical tuple if necessary.
495510
*/
496-
if (slot->tts_shouldFree)
511+
if (TTS_SHOULDFREE(slot))
512+
{
497513
heap_freetuple(slot->tts_tuple);
498-
if (slot->tts_shouldFreeMin)
514+
slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
515+
}
516+
if (TTS_SHOULDFREEMIN(slot))
517+
{
499518
heap_free_minimal_tuple(slot->tts_mintuple);
519+
slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
520+
}
500521

501522
slot->tts_tuple = NULL;
502523
slot->tts_mintuple = NULL;
503-
slot->tts_shouldFree = false;
504-
slot->tts_shouldFreeMin = false;
505524

506525
/*
507526
* Drop the pin on the referenced buffer, if there is one.
@@ -514,7 +533,7 @@ ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */
514533
/*
515534
* Mark it empty.
516535
*/
517-
slot->tts_isempty = true;
536+
slot->tts_flags |= TTS_FLAG_EMPTY;
518537
slot->tts_nvalid = 0;
519538

520539
return slot;
@@ -539,9 +558,9 @@ ExecStoreVirtualTuple(TupleTableSlot *slot)
539558
*/
540559
Assert(slot != NULL);
541560
Assert(slot->tts_tupleDescriptor != NULL);
542-
Assert(slot->tts_isempty);
561+
Assert(TTS_EMPTY(slot));
543562

544-
slot->tts_isempty = false;
563+
slot->tts_flags &= ~TTS_FLAG_EMPTY;
545564
slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
546565

547566
return slot;
@@ -595,7 +614,7 @@ ExecCopySlotTuple(TupleTableSlot *slot)
595614
* sanity checks
596615
*/
597616
Assert(slot != NULL);
598-
Assert(!slot->tts_isempty);
617+
Assert(!TTS_EMPTY(slot));
599618

600619
/*
601620
* If we have a physical tuple (either format) then just copy it.
@@ -627,7 +646,7 @@ ExecCopySlotMinimalTuple(TupleTableSlot *slot)
627646
* sanity checks
628647
*/
629648
Assert(slot != NULL);
630-
Assert(!slot->tts_isempty);
649+
Assert(!TTS_EMPTY(slot));
631650

632651
/*
633652
* If we have a physical tuple then just copy it. Prefer to copy
@@ -675,7 +694,7 @@ ExecFetchSlotTuple(TupleTableSlot *slot)
675694
* sanity checks
676695
*/
677696
Assert(slot != NULL);
678-
Assert(!slot->tts_isempty);
697+
Assert(!TTS_EMPTY(slot));
679698

680699
/*
681700
* If we have a regular physical tuple then just return it.
@@ -724,7 +743,8 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
724743
* sanity checks
725744
*/
726745
Assert(slot != NULL);
727-
Assert(!slot->tts_isempty);
746+
Assert(!TTS_EMPTY(slot));
747+
728748

729749
/*
730750
* If we have a minimal physical tuple (local or not) then just return it.
@@ -741,7 +761,7 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
741761
*/
742762
oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
743763
slot->tts_mintuple = ExecCopySlotMinimalTuple(slot);
744-
slot->tts_shouldFreeMin = true;
764+
slot->tts_flags |= TTS_FLAG_SHOULDFREEMIN;
745765
MemoryContextSwitchTo(oldContext);
746766

747767
/*
@@ -797,13 +817,13 @@ ExecMaterializeSlot(TupleTableSlot *slot)
797817
* sanity checks
798818
*/
799819
Assert(slot != NULL);
800-
Assert(!slot->tts_isempty);
820+
Assert(!TTS_EMPTY(slot));
801821

802822
/*
803823
* If we have a regular physical tuple, and it's locally palloc'd, we have
804824
* nothing to do.
805825
*/
806-
if (slot->tts_tuple && slot->tts_shouldFree)
826+
if (slot->tts_tuple && TTS_SHOULDFREE(slot))
807827
return slot->tts_tuple;
808828

809829
/*
@@ -815,7 +835,7 @@ ExecMaterializeSlot(TupleTableSlot *slot)
815835
*/
816836
oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
817837
slot->tts_tuple = ExecCopySlotTuple(slot);
818-
slot->tts_shouldFree = true;
838+
slot->tts_flags |= TTS_FLAG_SHOULDFREE;
819839
MemoryContextSwitchTo(oldContext);
820840

821841
/*
@@ -842,7 +862,7 @@ ExecMaterializeSlot(TupleTableSlot *slot)
842862
* storage, we must not pfree it now, since callers might have already
843863
* fetched datum pointers referencing it.)
844864
*/
845-
if (!slot->tts_shouldFreeMin)
865+
if (!TTS_SHOULDFREEMIN(slot))
846866
slot->tts_mintuple = NULL;
847867

848868
return slot->tts_tuple;

src/backend/executor/nodeAgg.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,7 @@ prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet
10801080

10811081
aggstate->grouped_cols = grouped_cols;
10821082

1083-
if (slot->tts_isempty)
1083+
if (TTS_EMPTY(slot))
10841084
{
10851085
/*
10861086
* Force all values to be NULL if working on an empty input tuple

src/backend/executor/nodeModifyTable.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ ExecDelete(ModifyTableState *mtstate,
699699
* RETURNING expressions might reference the tableoid column, so
700700
* initialize t_tableOid before evaluating them.
701701
*/
702-
if (slot->tts_isempty)
702+
if (TTS_EMPTY(slot))
703703
ExecStoreAllNullTuple(slot);
704704
tuple = ExecMaterializeSlot(slot);
705705
tuple->t_tableOid = RelationGetRelid(resultRelationDesc);

src/backend/jit/llvm/llvmjit_deform.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
6060
LLVMValueRef v_tts_values;
6161
LLVMValueRef v_tts_nulls;
6262
LLVMValueRef v_slotoffp;
63-
LLVMValueRef v_slowp;
63+
LLVMValueRef v_flagsp;
6464
LLVMValueRef v_nvalidp;
6565
LLVMValueRef v_nvalid;
6666
LLVMValueRef v_maxatt;
@@ -168,7 +168,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
168168
"tts_ISNULL");
169169

170170
v_slotoffp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_OFF, "");
171-
v_slowp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_SLOW, "");
171+
v_flagsp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
172172
v_nvalidp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
173173

174174
v_tupleheaderp =
@@ -690,11 +690,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
690690

691691
{
692692
LLVMValueRef v_off = LLVMBuildLoad(b, v_offp, "");
693+
LLVMValueRef v_flags;
693694

694695
LLVMBuildStore(b, l_int16_const(natts), v_nvalidp);
695696
v_off = LLVMBuildTrunc(b, v_off, LLVMInt32Type(), "");
696697
LLVMBuildStore(b, v_off, v_slotoffp);
697-
LLVMBuildStore(b, l_int8_const(1), v_slowp);
698+
v_flags = LLVMBuildLoad(b, v_flagsp, "tts_flags");
699+
v_flags = LLVMBuildOr(b, v_flags, l_int16_const(TTS_FLAG_SLOW), "");
700+
LLVMBuildStore(b, v_flags, v_flagsp);
698701
LLVMBuildRetVoid(b);
699702
}
700703

src/backend/jit/llvm/llvmjit_expr.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ llvm_compile_expr(ExprState *state)
292292
if (!desc &&
293293
is &&
294294
is->ps_ResultTupleSlot &&
295-
is->ps_ResultTupleSlot->tts_fixedTupleDescriptor)
295+
TTS_FIXED(is->ps_ResultTupleSlot))
296296
desc = is->ps_ResultTupleSlot->tts_tupleDescriptor;
297297
}
298298
else if (opcode == EEOP_OUTER_FETCHSOME)
@@ -304,7 +304,7 @@ llvm_compile_expr(ExprState *state)
304304
if (!desc &&
305305
os &&
306306
os->ps_ResultTupleSlot &&
307-
os->ps_ResultTupleSlot->tts_fixedTupleDescriptor)
307+
TTS_FIXED(os->ps_ResultTupleSlot))
308308
desc = os->ps_ResultTupleSlot->tts_tupleDescriptor;
309309
}
310310
else

src/include/executor/executor.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ ExecProject(ProjectionInfo *projInfo)
340340
* Successfully formed a result row. Mark the result slot as containing a
341341
* valid virtual tuple (inlined version of ExecStoreVirtualTuple()).
342342
*/
343-
slot->tts_isempty = false;
343+
slot->tts_flags &= ~TTS_FLAG_EMPTY;
344344
slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
345345

346346
return slot;

0 commit comments

Comments
 (0)