Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcc9f08b

Browse files
committed
Move ExecProcNode from dispatch to function pointer based model.
This allows us to add stack-depth checks the first time an executornode is called, and skip that overhead on followingcalls. Additionally it yields a nice speedup.While it'd probably have been a good idea to have that check allalong, it has become more important after the new expressionevaluation framework inb8d7f05 - there's no stack depthcheck in common paths anymore now. We previously relied onExecEvalExpr() being executed somewhere.We should move towards that model for further routines, but as this isrequired for v10, it seems better to only do the necessary (whichalready is quite large).Author: Andres Freund, Tom LaneReported-By: Julien RouhaudDiscussion:https://postgr.es/m/22833.1490390175@sss.pgh.pa.ushttps://postgr.es/m/b0af9eaa-130c-60d0-9e4e-7a135b1e0c76@dalibo.com
1 parentd47cfef commitcc9f08b

File tree

78 files changed

+313
-299
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+313
-299
lines changed

‎src/backend/executor/execProcnode.c

Lines changed: 66 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,10 @@
1717
*-------------------------------------------------------------------------
1818
*/
1919
/*
20-
* INTERFACE ROUTINES
21-
*ExecInitNode-initialize a plan node and its subplans
22-
*ExecProcNode-get a tuple by executing the plan node
23-
*ExecEndNode-shut down a plan node and its subplans
24-
*
2520
* NOTES
2621
*This used to be three files. It is now all combined into
27-
*one file so that it is easier to keepExecInitNode, ExecProcNode,
28-
*and ExecEndNodein sync when new nodes are added.
22+
*one file so that it is easier to keepthe dispatch routines
23+
*in sync when new nodes are added.
2924
*
3025
* EXAMPLE
3126
*Suppose we want the age of the manager of the shoe department and
@@ -122,6 +117,10 @@
122117
#include"miscadmin.h"
123118

124119

120+
staticTupleTableSlot*ExecProcNodeFirst(PlanState*node);
121+
staticTupleTableSlot*ExecProcNodeInstr(PlanState*node);
122+
123+
125124
/* ------------------------------------------------------------------------
126125
*ExecInitNode
127126
*
@@ -149,6 +148,13 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
149148
if (node==NULL)
150149
returnNULL;
151150

151+
/*
152+
* Make sure there's enough stack available. Need to check here, in
153+
* addition to ExecProcNode() (via ExecProcNodeFirst()), to ensure the
154+
* stack isn't overrun while initializing the node tree.
155+
*/
156+
check_stack_depth();
157+
152158
switch (nodeTag(node))
153159
{
154160
/*
@@ -364,6 +370,13 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
364370
break;
365371
}
366372

373+
/*
374+
* Add a wrapper around the ExecProcNode callback that checks stack depth
375+
* during the first execution.
376+
*/
377+
result->ExecProcNodeReal=result->ExecProcNode;
378+
result->ExecProcNode=ExecProcNodeFirst;
379+
367380
/*
368381
* Initialize any initPlans present in this node. The planner put them in
369382
* a separate list for us.
@@ -388,195 +401,51 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
388401
}
389402

390403

391-
/* ----------------------------------------------------------------
392-
*ExecProcNode
393-
*
394-
*Execute the given node to return a(nother) tuple.
395-
* ----------------------------------------------------------------
404+
/*
405+
* ExecProcNode wrapper that performs some one-time checks, before calling
406+
* the relevant node method (possibly via an instrumentation wrapper).
396407
*/
397-
TupleTableSlot*
398-
ExecProcNode(PlanState*node)
408+
staticTupleTableSlot*
409+
ExecProcNodeFirst(PlanState*node)
399410
{
400-
TupleTableSlot*result;
401-
402-
if (node->chgParam!=NULL)/* something changed */
403-
ExecReScan(node);/* let ReScan handle this */
411+
/*
412+
* Perform stack depth check during the first execution of the node. We
413+
* only do so the first time round because it turns out to not be cheap on
414+
* some common architectures (eg. x86). This relies on the assumption that
415+
* ExecProcNode calls for a given plan node will always be made at roughly
416+
* the same stack depth.
417+
*/
418+
check_stack_depth();
404419

420+
/*
421+
* If instrumentation is required, change the wrapper to one that just
422+
* does instrumentation. Otherwise we can dispense with all wrappers and
423+
* have ExecProcNode() directly call the relevant function from now on.
424+
*/
405425
if (node->instrument)
406-
InstrStartNode(node->instrument);
407-
408-
switch (nodeTag(node))
409-
{
410-
/*
411-
* control nodes
412-
*/
413-
caseT_ResultState:
414-
result=ExecResult((ResultState*)node);
415-
break;
416-
417-
caseT_ProjectSetState:
418-
result=ExecProjectSet((ProjectSetState*)node);
419-
break;
420-
421-
caseT_ModifyTableState:
422-
result=ExecModifyTable((ModifyTableState*)node);
423-
break;
424-
425-
caseT_AppendState:
426-
result=ExecAppend((AppendState*)node);
427-
break;
428-
429-
caseT_MergeAppendState:
430-
result=ExecMergeAppend((MergeAppendState*)node);
431-
break;
432-
433-
caseT_RecursiveUnionState:
434-
result=ExecRecursiveUnion((RecursiveUnionState*)node);
435-
break;
436-
437-
/* BitmapAndState does not yield tuples */
438-
439-
/* BitmapOrState does not yield tuples */
440-
441-
/*
442-
* scan nodes
443-
*/
444-
caseT_SeqScanState:
445-
result=ExecSeqScan((SeqScanState*)node);
446-
break;
447-
448-
caseT_SampleScanState:
449-
result=ExecSampleScan((SampleScanState*)node);
450-
break;
451-
452-
caseT_IndexScanState:
453-
result=ExecIndexScan((IndexScanState*)node);
454-
break;
455-
456-
caseT_IndexOnlyScanState:
457-
result=ExecIndexOnlyScan((IndexOnlyScanState*)node);
458-
break;
459-
460-
/* BitmapIndexScanState does not yield tuples */
461-
462-
caseT_BitmapHeapScanState:
463-
result=ExecBitmapHeapScan((BitmapHeapScanState*)node);
464-
break;
465-
466-
caseT_TidScanState:
467-
result=ExecTidScan((TidScanState*)node);
468-
break;
469-
470-
caseT_SubqueryScanState:
471-
result=ExecSubqueryScan((SubqueryScanState*)node);
472-
break;
473-
474-
caseT_FunctionScanState:
475-
result=ExecFunctionScan((FunctionScanState*)node);
476-
break;
477-
478-
caseT_TableFuncScanState:
479-
result=ExecTableFuncScan((TableFuncScanState*)node);
480-
break;
481-
482-
caseT_ValuesScanState:
483-
result=ExecValuesScan((ValuesScanState*)node);
484-
break;
485-
486-
caseT_CteScanState:
487-
result=ExecCteScan((CteScanState*)node);
488-
break;
489-
490-
caseT_NamedTuplestoreScanState:
491-
result=ExecNamedTuplestoreScan((NamedTuplestoreScanState*)node);
492-
break;
493-
494-
caseT_WorkTableScanState:
495-
result=ExecWorkTableScan((WorkTableScanState*)node);
496-
break;
497-
498-
caseT_ForeignScanState:
499-
result=ExecForeignScan((ForeignScanState*)node);
500-
break;
501-
502-
caseT_CustomScanState:
503-
result=ExecCustomScan((CustomScanState*)node);
504-
break;
505-
506-
/*
507-
* join nodes
508-
*/
509-
caseT_NestLoopState:
510-
result=ExecNestLoop((NestLoopState*)node);
511-
break;
512-
513-
caseT_MergeJoinState:
514-
result=ExecMergeJoin((MergeJoinState*)node);
515-
break;
516-
517-
caseT_HashJoinState:
518-
result=ExecHashJoin((HashJoinState*)node);
519-
break;
520-
521-
/*
522-
* materialization nodes
523-
*/
524-
caseT_MaterialState:
525-
result=ExecMaterial((MaterialState*)node);
526-
break;
527-
528-
caseT_SortState:
529-
result=ExecSort((SortState*)node);
530-
break;
531-
532-
caseT_GroupState:
533-
result=ExecGroup((GroupState*)node);
534-
break;
426+
node->ExecProcNode=ExecProcNodeInstr;
427+
else
428+
node->ExecProcNode=node->ExecProcNodeReal;
535429

536-
caseT_AggState:
537-
result=ExecAgg((AggState*)node);
538-
break;
539-
540-
caseT_WindowAggState:
541-
result=ExecWindowAgg((WindowAggState*)node);
542-
break;
543-
544-
caseT_UniqueState:
545-
result=ExecUnique((UniqueState*)node);
546-
break;
547-
548-
caseT_GatherState:
549-
result=ExecGather((GatherState*)node);
550-
break;
551-
552-
caseT_GatherMergeState:
553-
result=ExecGatherMerge((GatherMergeState*)node);
554-
break;
555-
556-
caseT_HashState:
557-
result=ExecHash((HashState*)node);
558-
break;
430+
returnnode->ExecProcNode(node);
431+
}
559432

560-
caseT_SetOpState:
561-
result=ExecSetOp((SetOpState*)node);
562-
break;
563433

564-
caseT_LockRowsState:
565-
result=ExecLockRows((LockRowsState*)node);
566-
break;
434+
/*
435+
* ExecProcNode wrapper that performs instrumentation calls. By keeping
436+
* this a separate function, we avoid overhead in the normal case where
437+
* no instrumentation is wanted.
438+
*/
439+
staticTupleTableSlot*
440+
ExecProcNodeInstr(PlanState*node)
441+
{
442+
TupleTableSlot*result;
567443

568-
caseT_LimitState:
569-
result=ExecLimit((LimitState*)node);
570-
break;
444+
InstrStartNode(node->instrument);
571445

572-
default:
573-
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(node));
574-
result=NULL;
575-
break;
576-
}
446+
result=node->ExecProcNodeReal(node);
577447

578-
if (node->instrument)
579-
InstrStopNode(node->instrument,TupIsNull(result) ?0.0 :1.0);
448+
InstrStopNode(node->instrument,TupIsNull(result) ?0.0 :1.0);
580449

581450
returnresult;
582451
}
@@ -600,6 +469,8 @@ MultiExecProcNode(PlanState *node)
600469
{
601470
Node*result;
602471

472+
check_stack_depth();
473+
603474
CHECK_FOR_INTERRUPTS();
604475

605476
if (node->chgParam!=NULL)/* something changed */
@@ -657,6 +528,13 @@ ExecEndNode(PlanState *node)
657528
if (node==NULL)
658529
return;
659530

531+
/*
532+
* Make sure there's enough stack available. Need to check here, in
533+
* addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
534+
* guaranteed that ExecProcNode() is reached for all nodes.
535+
*/
536+
check_stack_depth();
537+
660538
if (node->chgParam!=NULL)
661539
{
662540
bms_free(node->chgParam);
@@ -855,6 +733,8 @@ ExecShutdownNode(PlanState *node)
855733
if (node==NULL)
856734
return false;
857735

736+
check_stack_depth();
737+
858738
planstate_tree_walker(node,ExecShutdownNode,NULL);
859739

860740
switch (nodeTag(node))

‎src/backend/executor/nodeAgg.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,9 +2099,10 @@ lookup_hash_entries(AggState *aggstate)
20992099
* stored in the expression context to be used when ExecProject evaluates
21002100
* the result tuple.
21012101
*/
2102-
TupleTableSlot*
2103-
ExecAgg(AggState*node)
2102+
staticTupleTableSlot*
2103+
ExecAgg(PlanState*pstate)
21042104
{
2105+
AggState*node=castNode(AggState,pstate);
21052106
TupleTableSlot*result=NULL;
21062107

21072108
CHECK_FOR_INTERRUPTS();
@@ -2695,6 +2696,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
26952696
aggstate=makeNode(AggState);
26962697
aggstate->ss.ps.plan= (Plan*)node;
26972698
aggstate->ss.ps.state=estate;
2699+
aggstate->ss.ps.ExecProcNode=ExecAgg;
26982700

26992701
aggstate->aggs=NIL;
27002702
aggstate->numaggs=0;

‎src/backend/executor/nodeAppend.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include"executor/nodeAppend.h"
6262
#include"miscadmin.h"
6363

64+
staticTupleTableSlot*ExecAppend(PlanState*pstate);
6465
staticboolexec_append_initialize_next(AppendState*appendstate);
6566

6667

@@ -147,6 +148,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
147148
*/
148149
appendstate->ps.plan= (Plan*)node;
149150
appendstate->ps.state=estate;
151+
appendstate->ps.ExecProcNode=ExecAppend;
150152
appendstate->appendplans=appendplanstates;
151153
appendstate->as_nplans=nplans;
152154

@@ -197,9 +199,11 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
197199
*Handles iteration over multiple subplans.
198200
* ----------------------------------------------------------------
199201
*/
200-
TupleTableSlot*
201-
ExecAppend(AppendState*node)
202+
staticTupleTableSlot*
203+
ExecAppend(PlanState*pstate)
202204
{
205+
AppendState*node=castNode(AppendState,pstate);
206+
203207
for (;;)
204208
{
205209
PlanState*subnode;

‎src/backend/executor/nodeBitmapAnd.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@
3232
#include"executor/nodeBitmapAnd.h"
3333

3434

35+
/* ----------------------------------------------------------------
36+
*ExecBitmapAnd
37+
*
38+
*stub for pro forma compliance
39+
* ----------------------------------------------------------------
40+
*/
41+
staticTupleTableSlot*
42+
ExecBitmapAnd(PlanState*pstate)
43+
{
44+
elog(ERROR,"BitmapAnd node does not support ExecProcNode call convention");
45+
returnNULL;
46+
}
47+
3548
/* ----------------------------------------------------------------
3649
*ExecInitBitmapAnd
3750
*
@@ -63,6 +76,7 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
6376
*/
6477
bitmapandstate->ps.plan= (Plan*)node;
6578
bitmapandstate->ps.state=estate;
79+
bitmapandstate->ps.ExecProcNode=ExecBitmapAnd;
6680
bitmapandstate->bitmapplans=bitmapplanstates;
6781
bitmapandstate->nplans=nplans;
6882

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp