Skip to content

Commit 9b5b961

Browse files
committed
Remove explicit FreeExprContext calls during plan node shutdown. The
ExprContexts will be freed anyway when FreeExecutorState() is reached, and letting that routine do the work is more efficient because it will automatically free the ExprContexts in reverse creation order. The existing coding was effectively freeing them in exactly the worst possible order, resulting in O(N^2) behavior inside list_delete_ptr, which becomes highly visible in cases with a few thousand plan nodes. ExecFreeExprContext is now effectively a no-op and could be removed, but I left it in place in case we ever want to put it back to use.
1 parent 95c7bff commit 9b5b961

File tree

3 files changed

+21
-18
lines changed

3 files changed

+21
-18
lines changed

src/backend/executor/execUtils.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.121 2005/04/14 20:03:24 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.122 2005/04/23 21:32:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -620,27 +620,26 @@ ExecAssignProjectionInfo(PlanState *planstate)
620620
/* ----------------
621621
* ExecFreeExprContext
622622
*
623-
* A plan node's ExprContext should be freed explicitly during ExecEndNode
624-
* because there may be shutdown callbacks to call. (Other resources made
625-
* by the above routines, such as projection info, don't need to be freed
623+
* A plan node's ExprContext should be freed explicitly during executor
624+
* shutdown because there may be shutdown callbacks to call. (Other resources
625+
* made by the above routines, such as projection info, don't need to be freed
626626
* explicitly because they're just memory in the per-query memory context.)
627+
*
628+
* However ... there is no particular need to do it during ExecEndNode,
629+
* because FreeExecutorState will free any remaining ExprContexts within
630+
* the EState. Letting FreeExecutorState do it allows the ExprContexts to
631+
* be freed in reverse order of creation, rather than order of creation as
632+
* will happen if we delete them here, which saves O(N^2) work in the list
633+
* cleanup inside FreeExprContext.
627634
* ----------------
628635
*/
629636
void
630637
ExecFreeExprContext(PlanState *planstate)
631638
{
632-
ExprContext *econtext;
633-
634639
/*
635-
* get expression context. if NULL then this node has none so we just
636-
* return.
640+
* Per above discussion, don't actually delete the ExprContext.
641+
* We do unlink it from the plan node, though.
637642
*/
638-
econtext = planstate->ps_ExprContext;
639-
if (econtext == NULL)
640-
return;
641-
642-
FreeExprContext(econtext);
643-
644643
planstate->ps_ExprContext = NULL;
645644
}
646645

src/backend/executor/nodeBitmapIndexscan.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.3 2005/04/22 21:58:31 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.4 2005/04/23 21:32:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -220,11 +220,13 @@ ExecEndBitmapIndexScan(BitmapIndexScanState *node)
220220
relation = node->ss.ss_currentRelation;
221221

222222
/*
223-
* Free the exprcontext(s)
223+
* Free the exprcontext(s) ... now dead code, see ExecFreeExprContext
224224
*/
225+
#ifdef NOT_USED
225226
ExecFreeExprContext(&node->ss.ps);
226227
if (node->biss_RuntimeContext)
227228
FreeExprContext(node->biss_RuntimeContext);
229+
#endif
228230

229231
/*
230232
* close the index relation

src/backend/executor/nodeIndexscan.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.100 2005/03/16 21:38:07 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.101 2005/04/23 21:32:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -534,11 +534,13 @@ ExecEndIndexScan(IndexScanState *node)
534534
relation = node->ss.ss_currentRelation;
535535

536536
/*
537-
* Free the exprcontext(s)
537+
* Free the exprcontext(s) ... now dead code, see ExecFreeExprContext
538538
*/
539+
#ifdef NOT_USED
539540
ExecFreeExprContext(&node->ss.ps);
540541
if (node->iss_RuntimeContext)
541542
FreeExprContext(node->iss_RuntimeContext);
543+
#endif
542544

543545
/*
544546
* clear out tuple table slots

0 commit comments

Comments
 (0)