From 0032774bacdeff43d6565e43e04510c1b1eaf6c2 Mon Sep 17 00:00:00 2001 From: Lukas Fittl Date: Sat, 7 Mar 2026 01:19:50 -0800 Subject: [PATCH v7 2/8] instrumentation: Separate per-node logic from other uses Previously different places (e.g. query "total time") were repurposing the Instrumentation struct initially introduced for capturing per-node statistics during execution. This overuse of the same struct is confusing, e.g. by cluttering calls of InstrStartNode/InstrStopNode in unrelated code paths, and prevents future refactorings. Instead, simplify the Instrumentation struct to only track time and WAL/buffer usage. Similarly, drop the use of InstrEndLoop outside of per-node instrumentation - these calls were added without any apparent benefit since the relevant fields were never read. Introduce the NodeInstrumentation struct to carry forward the per-node instrumentation information. WorkerInstrumentation is renamed to WorkerNodeInstrumentation for clarity. In passing, drop the "n" argument to InstrAlloc, as all remaining callers need exactly one Instrumentation struct. Author: Lukas Fittl Reviewed-by: Discussion: --- contrib/auto_explain/auto_explain.c | 8 +- .../pg_stat_statements/pg_stat_statements.c | 8 +- contrib/postgres_fdw/postgres_fdw.c | 2 +- src/backend/commands/explain.c | 20 +-- src/backend/executor/execMain.c | 8 +- src/backend/executor/execParallel.c | 24 +-- src/backend/executor/execProcnode.c | 4 +- src/backend/executor/instrument.c | 142 ++++++++++++------ src/include/executor/instrument.h | 60 +++++--- src/include/nodes/execnodes.h | 6 +- src/tools/pgindent/typedefs.list | 3 +- 11 files changed, 172 insertions(+), 113 deletions(-) diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c index e856cd35a6f..39bf2543b70 100644 --- a/contrib/auto_explain/auto_explain.c +++ b/contrib/auto_explain/auto_explain.c @@ -315,7 +315,7 @@ explain_ExecutorStart(QueryDesc *queryDesc, int eflags) MemoryContext oldcxt; oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt); - queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL, false); + queryDesc->totaltime = InstrAlloc(INSTRUMENT_ALL); MemoryContextSwitchTo(oldcxt); } } @@ -381,12 +381,6 @@ explain_ExecutorEnd(QueryDesc *queryDesc) */ oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt); - /* - * Make sure stats accumulation is done. (Note: it's okay if several - * levels of hook all do this.) - */ - InstrEndLoop(queryDesc->totaltime); - /* Log plan if duration is exceeded. */ msec = INSTR_TIME_GET_MILLISEC(queryDesc->totaltime->total); if (msec >= auto_explain_log_min_duration) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 4a427533bd8..388b068ccec 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1023,7 +1023,7 @@ pgss_ExecutorStart(QueryDesc *queryDesc, int eflags) MemoryContext oldcxt; oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt); - queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL, false); + queryDesc->totaltime = InstrAlloc(INSTRUMENT_ALL); MemoryContextSwitchTo(oldcxt); } } @@ -1082,12 +1082,6 @@ pgss_ExecutorEnd(QueryDesc *queryDesc) if (queryId != INT64CONST(0) && queryDesc->totaltime && pgss_enabled(nesting_level)) { - /* - * Make sure stats accumulation is done. (Note: it's okay if several - * levels of hook all do this.) - */ - InstrEndLoop(queryDesc->totaltime); - pgss_store(queryDesc->sourceText, queryId, queryDesc->plannedstmt->stmt_location, diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 60d90329a65..6f0cb2a285b 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -2778,7 +2778,7 @@ postgresIterateDirectModify(ForeignScanState *node) if (!resultRelInfo->ri_projectReturning) { TupleTableSlot *slot = node->ss.ss_ScanTupleSlot; - Instrumentation *instr = node->ss.ps.instrument; + NodeInstrumentation *instr = node->ss.ps.instrument; Assert(!dmstate->has_returning); diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 09b13807d92..389181b8d9b 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -1835,7 +1835,7 @@ ExplainNode(PlanState *planstate, List *ancestors, { double nloops = planstate->instrument->nloops; double startup_ms = INSTR_TIME_GET_MILLISEC(planstate->instrument->startup) / nloops; - double total_ms = INSTR_TIME_GET_MILLISEC(planstate->instrument->total) / nloops; + double total_ms = INSTR_TIME_GET_MILLISEC(planstate->instrument->instr.total) / nloops; double rows = planstate->instrument->ntuples / nloops; if (es->format == EXPLAIN_FORMAT_TEXT) @@ -1888,11 +1888,11 @@ ExplainNode(PlanState *planstate, List *ancestors, /* prepare per-worker general execution details */ if (es->workers_state && es->verbose) { - WorkerInstrumentation *w = planstate->worker_instrument; + WorkerNodeInstrumentation *w = planstate->worker_instrument; for (int n = 0; n < w->num_workers; n++) { - Instrumentation *instrument = &w->instrument[n]; + NodeInstrumentation *instrument = &w->instrument[n]; double nloops = instrument->nloops; double startup_ms; double total_ms; @@ -1901,7 +1901,7 @@ ExplainNode(PlanState *planstate, List *ancestors, if (nloops <= 0) continue; startup_ms = INSTR_TIME_GET_MILLISEC(instrument->startup) / nloops; - total_ms = INSTR_TIME_GET_MILLISEC(instrument->total) / nloops; + total_ms = INSTR_TIME_GET_MILLISEC(instrument->instr.total) / nloops; rows = instrument->ntuples / nloops; ExplainOpenWorker(n, es); @@ -2288,18 +2288,18 @@ ExplainNode(PlanState *planstate, List *ancestors, /* Show buffer/WAL usage */ if (es->buffers && planstate->instrument) - show_buffer_usage(es, &planstate->instrument->bufusage); + show_buffer_usage(es, &planstate->instrument->instr.bufusage); if (es->wal && planstate->instrument) - show_wal_usage(es, &planstate->instrument->walusage); + show_wal_usage(es, &planstate->instrument->instr.walusage); /* Prepare per-worker buffer/WAL usage */ if (es->workers_state && (es->buffers || es->wal) && es->verbose) { - WorkerInstrumentation *w = planstate->worker_instrument; + WorkerNodeInstrumentation *w = planstate->worker_instrument; for (int n = 0; n < w->num_workers; n++) { - Instrumentation *instrument = &w->instrument[n]; + NodeInstrumentation *instrument = &w->instrument[n]; double nloops = instrument->nloops; if (nloops <= 0) @@ -2307,9 +2307,9 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainOpenWorker(n, es); if (es->buffers) - show_buffer_usage(es, &instrument->bufusage); + show_buffer_usage(es, &instrument->instr.bufusage); if (es->wal) - show_wal_usage(es, &instrument->walusage); + show_wal_usage(es, &instrument->instr.walusage); ExplainCloseWorker(n, es); } } diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 1a3b8021600..c0b174cfbc0 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -331,7 +331,7 @@ standard_ExecutorRun(QueryDesc *queryDesc, /* Allow instrumentation of Executor overall runtime */ if (queryDesc->totaltime) - InstrStartNode(queryDesc->totaltime); + InstrStart(queryDesc->totaltime); /* * extract information from the query descriptor and the query feature. @@ -383,7 +383,7 @@ standard_ExecutorRun(QueryDesc *queryDesc, dest->rShutdown(dest); if (queryDesc->totaltime) - InstrStopNode(queryDesc->totaltime, estate->es_processed); + InstrStop(queryDesc->totaltime); MemoryContextSwitchTo(oldcontext); } @@ -433,7 +433,7 @@ standard_ExecutorFinish(QueryDesc *queryDesc) /* Allow instrumentation of Executor overall runtime */ if (queryDesc->totaltime) - InstrStartNode(queryDesc->totaltime); + InstrStart(queryDesc->totaltime); /* Run ModifyTable nodes to completion */ ExecPostprocessPlan(estate); @@ -443,7 +443,7 @@ standard_ExecutorFinish(QueryDesc *queryDesc) AfterTriggerEndQuery(estate); if (queryDesc->totaltime) - InstrStopNode(queryDesc->totaltime, 0); + InstrStop(queryDesc->totaltime); MemoryContextSwitchTo(oldcontext); diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index ac84af294c9..c153d5c1c3b 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -87,7 +87,7 @@ typedef struct FixedParallelExecutorState * instrument_options: Same meaning here as in instrument.c. * * instrument_offset: Offset, relative to the start of this structure, - * of the first Instrumentation object. This will depend on the length of + * of the first NodeInstrumentation object. This will depend on the length of * the plan_node_id array. * * num_workers: Number of workers. @@ -104,11 +104,15 @@ struct SharedExecutorInstrumentation int num_workers; int num_plan_nodes; int plan_node_id[FLEXIBLE_ARRAY_MEMBER]; - /* array of num_plan_nodes * num_workers Instrumentation objects follows */ + + /* + * array of num_plan_nodes * num_workers NodeInstrumentation objects + * follows + */ }; #define GetInstrumentationArray(sei) \ (StaticAssertVariableIsOfTypeMacro(sei, SharedExecutorInstrumentation *), \ - (Instrumentation *) (((char *) sei) + sei->instrument_offset)) + (NodeInstrumentation *) (((char *) sei) + sei->instrument_offset)) /* Context object for ExecParallelEstimate. */ typedef struct ExecParallelEstimateContext @@ -725,7 +729,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, instrumentation_len = MAXALIGN(instrumentation_len); instrument_offset = instrumentation_len; instrumentation_len += - mul_size(sizeof(Instrumentation), + mul_size(sizeof(NodeInstrumentation), mul_size(e.nnodes, nworkers)); shm_toc_estimate_chunk(&pcxt->estimator, instrumentation_len); shm_toc_estimate_keys(&pcxt->estimator, 1); @@ -811,7 +815,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, */ if (estate->es_instrument) { - Instrumentation *instrument; + NodeInstrumentation *instrument; int i; instrumentation = shm_toc_allocate(pcxt->toc, instrumentation_len); @@ -821,7 +825,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, instrumentation->num_plan_nodes = e.nnodes; instrument = GetInstrumentationArray(instrumentation); for (i = 0; i < nworkers * e.nnodes; ++i) - InstrInit(&instrument[i], estate->es_instrument); + InstrInitNode(&instrument[i], estate->es_instrument); shm_toc_insert(pcxt->toc, PARALLEL_KEY_INSTRUMENTATION, instrumentation); pei->instrumentation = instrumentation; @@ -1053,7 +1057,7 @@ static bool ExecParallelRetrieveInstrumentation(PlanState *planstate, SharedExecutorInstrumentation *instrumentation) { - Instrumentation *instrument; + NodeInstrumentation *instrument; int i; int n; int ibytes; @@ -1081,9 +1085,9 @@ ExecParallelRetrieveInstrumentation(PlanState *planstate, * Switch into per-query memory context. */ oldcontext = MemoryContextSwitchTo(planstate->state->es_query_cxt); - ibytes = mul_size(instrumentation->num_workers, sizeof(Instrumentation)); + ibytes = mul_size(instrumentation->num_workers, sizeof(NodeInstrumentation)); planstate->worker_instrument = - palloc(ibytes + offsetof(WorkerInstrumentation, instrument)); + palloc(ibytes + offsetof(WorkerNodeInstrumentation, instrument)); MemoryContextSwitchTo(oldcontext); planstate->worker_instrument->num_workers = instrumentation->num_workers; @@ -1313,7 +1317,7 @@ ExecParallelReportInstrumentation(PlanState *planstate, { int i; int plan_node_id = planstate->plan->plan_node_id; - Instrumentation *instrument; + NodeInstrumentation *instrument; InstrEndLoop(planstate->instrument); diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 7e40b852517..1846661b503 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -413,8 +413,8 @@ ExecInitNode(Plan *node, EState *estate, int eflags) /* Set up instrumentation for this node if requested */ if (estate->es_instrument) - result->instrument = InstrAlloc(1, estate->es_instrument, - result->async_capable); + result->instrument = InstrAllocNode(estate->es_instrument, + result->async_capable); return result; } diff --git a/src/backend/executor/instrument.c b/src/backend/executor/instrument.c index 9354ad7be12..bc551f95a08 100644 --- a/src/backend/executor/instrument.c +++ b/src/backend/executor/instrument.c @@ -26,51 +26,30 @@ static void BufferUsageAdd(BufferUsage *dst, const BufferUsage *add); static void WalUsageAdd(WalUsage *dst, WalUsage *add); -/* Allocate new instrumentation structure(s) */ +/* General purpose instrumentation handling */ Instrumentation * -InstrAlloc(int n, int instrument_options, bool async_mode) +InstrAlloc(int instrument_options) { - Instrumentation *instr; - - /* initialize all fields to zeroes, then modify as needed */ - instr = palloc0(n * sizeof(Instrumentation)); - if (instrument_options & (INSTRUMENT_BUFFERS | INSTRUMENT_TIMER | INSTRUMENT_WAL)) - { - bool need_buffers = (instrument_options & INSTRUMENT_BUFFERS) != 0; - bool need_wal = (instrument_options & INSTRUMENT_WAL) != 0; - bool need_timer = (instrument_options & INSTRUMENT_TIMER) != 0; - int i; - - for (i = 0; i < n; i++) - { - instr[i].need_bufusage = need_buffers; - instr[i].need_walusage = need_wal; - instr[i].need_timer = need_timer; - instr[i].async_mode = async_mode; - } - } - + Instrumentation *instr = palloc0(sizeof(Instrumentation)); + InstrInitOptions(instr, instrument_options); return instr; } -/* Initialize a pre-allocated instrumentation structure. */ void -InstrInit(Instrumentation *instr, int instrument_options) +InstrInitOptions(Instrumentation *instr, int instrument_options) { - memset(instr, 0, sizeof(Instrumentation)); instr->need_bufusage = (instrument_options & INSTRUMENT_BUFFERS) != 0; instr->need_walusage = (instrument_options & INSTRUMENT_WAL) != 0; instr->need_timer = (instrument_options & INSTRUMENT_TIMER) != 0; } -/* Entry to a plan node */ void -InstrStartNode(Instrumentation *instr) +InstrStart(Instrumentation *instr) { if (instr->need_timer) { if (!INSTR_TIME_IS_ZERO(instr->starttime)) - elog(ERROR, "InstrStartNode called twice in a row"); + elog(ERROR, "InstrStart called twice in a row"); else INSTR_TIME_SET_CURRENT(instr->starttime); } @@ -83,24 +62,19 @@ InstrStartNode(Instrumentation *instr) instr->walusage_start = pgWalUsage; } -/* Exit from a plan node */ void -InstrStopNode(Instrumentation *instr, double nTuples) +InstrStop(Instrumentation *instr) { - double save_tuplecount = instr->tuplecount; instr_time endtime; - /* count the returned tuples */ - instr->tuplecount += nTuples; - /* let's update the time only if the timer was requested */ if (instr->need_timer) { if (INSTR_TIME_IS_ZERO(instr->starttime)) - elog(ERROR, "InstrStopNode called without start"); + elog(ERROR, "InstrStop called without start"); INSTR_TIME_SET_CURRENT(endtime); - INSTR_TIME_ACCUM_DIFF(instr->counter, endtime, instr->starttime); + INSTR_TIME_ACCUM_DIFF(instr->total, endtime, instr->starttime); INSTR_TIME_SET_ZERO(instr->starttime); } @@ -113,6 +87,74 @@ InstrStopNode(Instrumentation *instr, double nTuples) if (instr->need_walusage) WalUsageAccumDiff(&instr->walusage, &pgWalUsage, &instr->walusage_start); +} + +/* Node instrumentation handling */ + +/* Allocate new node instrumentation structure */ +NodeInstrumentation * +InstrAllocNode(int instrument_options, bool async_mode) +{ + NodeInstrumentation *instr = palloc(sizeof(NodeInstrumentation)); + + InstrInitNode(instr, instrument_options); + instr->async_mode = async_mode; + + return instr; +} + +/* Initialize a pre-allocated instrumentation structure. */ +void +InstrInitNode(NodeInstrumentation *instr, int instrument_options) +{ + memset(instr, 0, sizeof(NodeInstrumentation)); + InstrInitOptions(&instr->instr, instrument_options); +} + +/* Entry to a plan node */ +void +InstrStartNode(NodeInstrumentation *instr) +{ + InstrStart(&instr->instr); +} + +/* Exit from a plan node */ +void +InstrStopNode(NodeInstrumentation *instr, double nTuples) +{ + double save_tuplecount = instr->tuplecount; + instr_time endtime; + + /* count the returned tuples */ + instr->tuplecount += nTuples; + + /* + * Update the time only if the timer was requested. + * + * Note this is different from InstrStop because total is only updated in + * InstrEndLoop. We need the separate counter variable because we need to + * calculate start-up time for the first tuple in each cycle, and then + * accumulate it together. + */ + if (instr->instr.need_timer) + { + if (INSTR_TIME_IS_ZERO(instr->instr.starttime)) + elog(ERROR, "InstrStopNode called without start"); + + INSTR_TIME_SET_CURRENT(endtime); + INSTR_TIME_ACCUM_DIFF(instr->counter, endtime, instr->instr.starttime); + + INSTR_TIME_SET_ZERO(instr->instr.starttime); + } + + /* Add delta of buffer usage since entry to node's totals */ + if (instr->instr.need_bufusage) + BufferUsageAccumDiff(&instr->instr.bufusage, + &pgBufferUsage, &instr->instr.bufusage_start); + + if (instr->instr.need_walusage) + WalUsageAccumDiff(&instr->instr.walusage, + &pgWalUsage, &instr->instr.walusage_start); /* Is this the first tuple of this cycle? */ if (!instr->running) @@ -133,7 +175,7 @@ InstrStopNode(Instrumentation *instr, double nTuples) /* Update tuple count */ void -InstrUpdateTupleCount(Instrumentation *instr, double nTuples) +InstrUpdateTupleCount(NodeInstrumentation *instr, double nTuples) { /* count the returned tuples */ instr->tuplecount += nTuples; @@ -141,24 +183,24 @@ InstrUpdateTupleCount(Instrumentation *instr, double nTuples) /* Finish a run cycle for a plan node */ void -InstrEndLoop(Instrumentation *instr) +InstrEndLoop(NodeInstrumentation *instr) { /* Skip if nothing has happened, or already shut down */ if (!instr->running) return; - if (!INSTR_TIME_IS_ZERO(instr->starttime)) + if (!INSTR_TIME_IS_ZERO(instr->instr.starttime)) elog(ERROR, "InstrEndLoop called on running node"); /* Accumulate per-cycle statistics into totals */ INSTR_TIME_ADD(instr->startup, instr->firsttuple); - INSTR_TIME_ADD(instr->total, instr->counter); + INSTR_TIME_ADD(instr->instr.total, instr->counter); instr->ntuples += instr->tuplecount; instr->nloops += 1; /* Reset for next cycle (if any) */ instr->running = false; - INSTR_TIME_SET_ZERO(instr->starttime); + INSTR_TIME_SET_ZERO(instr->instr.starttime); INSTR_TIME_SET_ZERO(instr->counter); INSTR_TIME_SET_ZERO(instr->firsttuple); instr->tuplecount = 0; @@ -166,7 +208,7 @@ InstrEndLoop(Instrumentation *instr) /* aggregate instrumentation information */ void -InstrAggNode(Instrumentation *dst, Instrumentation *add) +InstrAggNode(NodeInstrumentation *dst, NodeInstrumentation *add) { if (!dst->running && add->running) { @@ -181,7 +223,7 @@ InstrAggNode(Instrumentation *dst, Instrumentation *add) dst->tuplecount += add->tuplecount; INSTR_TIME_ADD(dst->startup, add->startup); - INSTR_TIME_ADD(dst->total, add->total); + INSTR_TIME_ADD(dst->instr.total, add->instr.total); dst->ntuples += add->ntuples; dst->ntuples2 += add->ntuples2; dst->nloops += add->nloops; @@ -189,11 +231,11 @@ InstrAggNode(Instrumentation *dst, Instrumentation *add) dst->nfiltered2 += add->nfiltered2; /* Add delta of buffer usage since entry to node's totals */ - if (dst->need_bufusage) - BufferUsageAdd(&dst->bufusage, &add->bufusage); + if (dst->instr.need_bufusage) + BufferUsageAdd(&dst->instr.bufusage, &add->instr.bufusage); - if (dst->need_walusage) - WalUsageAdd(&dst->walusage, &add->walusage); + if (dst->instr.need_walusage) + WalUsageAdd(&dst->instr.walusage, &add->instr.walusage); } /* Trigger instrumentation handling */ @@ -204,7 +246,7 @@ InstrAllocTrigger(int n, int instrument_options) int i; for (i = 0; i < n; i++) - InstrInit(&tginstr[i].instr, instrument_options); + InstrInitOptions(&tginstr[i].instr, instrument_options); return tginstr; } @@ -212,13 +254,13 @@ InstrAllocTrigger(int n, int instrument_options) void InstrStartTrigger(TriggerInstrumentation *tginstr) { - InstrStartNode(&tginstr->instr); + InstrStart(&tginstr->instr); } void InstrStopTrigger(TriggerInstrumentation *tginstr, int firings) { - InstrStopNode(&tginstr->instr, 0); + InstrStop(&tginstr->instr); tginstr->firings += firings; } diff --git a/src/include/executor/instrument.h b/src/include/executor/instrument.h index a9c2233227f..b11d64633b5 100644 --- a/src/include/executor/instrument.h +++ b/src/include/executor/instrument.h @@ -67,38 +67,55 @@ typedef enum InstrumentOption INSTRUMENT_ALL = PG_INT32_MAX } InstrumentOption; +/* + * General purpose instrumentation that can capture time and WAL/buffer usage + * + * Initialized through InstrAlloc, followed by one or more calls to a pair of + * InstrStart/InstrStop (activity is measured inbetween). + */ typedef struct Instrumentation { - /* Parameters set at node creation: */ + /* Parameters set at creation: */ bool need_timer; /* true if we need timer data */ bool need_bufusage; /* true if we need buffer usage data */ bool need_walusage; /* true if we need WAL usage data */ + /* Internal state keeping: */ + instr_time starttime; /* start time of last InstrStart */ + BufferUsage bufusage_start; /* buffer usage at start */ + WalUsage walusage_start; /* WAL usage at start */ + /* Accumulated statistics: */ + instr_time total; /* total runtime */ + BufferUsage bufusage; /* total buffer usage */ + WalUsage walusage; /* total WAL usage */ +} Instrumentation; + +/* + * Specialized instrumentation for per-node execution statistics + */ +typedef struct NodeInstrumentation +{ + Instrumentation instr; + /* Parameters set at node creation: */ bool async_mode; /* true if node is in async mode */ /* Info about current plan cycle: */ bool running; /* true if we've completed first tuple */ - instr_time starttime; /* start time of current iteration of node */ instr_time counter; /* accumulated runtime for this node */ instr_time firsttuple; /* time for first tuple of this cycle */ double tuplecount; /* # of tuples emitted so far this cycle */ - BufferUsage bufusage_start; /* buffer usage at start */ - WalUsage walusage_start; /* WAL usage at start */ /* Accumulated statistics across all completed cycles: */ instr_time startup; /* total startup time */ - instr_time total; /* total time */ double ntuples; /* total tuples produced */ double ntuples2; /* secondary node-specific tuple counter */ double nloops; /* # of run cycles for this node */ double nfiltered1; /* # of tuples removed by scanqual or joinqual */ double nfiltered2; /* # of tuples removed by "other" quals */ - BufferUsage bufusage; /* total buffer usage */ - WalUsage walusage; /* total WAL usage */ -} Instrumentation; +} NodeInstrumentation; -typedef struct WorkerInstrumentation +typedef struct WorkerNodeInstrumentation { int num_workers; /* # of structures that follow */ - Instrumentation instrument[FLEXIBLE_ARRAY_MEMBER]; -} WorkerInstrumentation; + NodeInstrumentation instrument[FLEXIBLE_ARRAY_MEMBER]; +} WorkerNodeInstrumentation; typedef struct TriggerInstrumentation { @@ -110,14 +127,19 @@ typedef struct TriggerInstrumentation extern PGDLLIMPORT BufferUsage pgBufferUsage; extern PGDLLIMPORT WalUsage pgWalUsage; -extern Instrumentation *InstrAlloc(int n, int instrument_options, - bool async_mode); -extern void InstrInit(Instrumentation *instr, int instrument_options); -extern void InstrStartNode(Instrumentation *instr); -extern void InstrStopNode(Instrumentation *instr, double nTuples); -extern void InstrUpdateTupleCount(Instrumentation *instr, double nTuples); -extern void InstrEndLoop(Instrumentation *instr); -extern void InstrAggNode(Instrumentation *dst, Instrumentation *add); +extern Instrumentation *InstrAlloc(int instrument_options); +extern void InstrInitOptions(Instrumentation *instr, int instrument_options); +extern void InstrStart(Instrumentation *instr); +extern void InstrStop(Instrumentation *instr); + +extern NodeInstrumentation *InstrAllocNode(int instrument_options, + bool async_mode); +extern void InstrInitNode(NodeInstrumentation *instr, int instrument_options); +extern void InstrStartNode(NodeInstrumentation *instr); +extern void InstrStopNode(NodeInstrumentation *instr, double nTuples); +extern void InstrUpdateTupleCount(NodeInstrumentation *instr, double nTuples); +extern void InstrEndLoop(NodeInstrumentation *instr); +extern void InstrAggNode(NodeInstrumentation *dst, NodeInstrumentation *add); extern TriggerInstrumentation *InstrAllocTrigger(int n, int instrument_options); extern void InstrStartTrigger(TriggerInstrumentation *tginstr); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index a43bd428a91..605c7a6cc39 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1175,8 +1175,10 @@ typedef struct PlanState ExecProcNodeMtd ExecProcNodeReal; /* actual function, if above is a * wrapper */ - Instrumentation *instrument; /* Optional runtime stats for this node */ - WorkerInstrumentation *worker_instrument; /* per-worker instrumentation */ + NodeInstrumentation *instrument; /* Optional runtime stats for this + * node */ + WorkerNodeInstrumentation *worker_instrument; /* per-worker + * instrumentation */ /* Per-worker JIT instrumentation */ struct SharedJitInstrumentation *worker_jit_instrument; diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index fd3ec7a7236..7dc0073ab68 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -1785,6 +1785,7 @@ NextSampleBlock_function NextSampleTuple_function NextValueExpr Node +NodeInstrumentation NodeTag NonEmptyRange NoneCompressorState @@ -3377,9 +3378,9 @@ WorkTableScan WorkTableScanState WorkerInfo WorkerInfoData -WorkerInstrumentation WorkerJobDumpPtrType WorkerJobRestorePtrType +WorkerNodeInstrumentation Working_State WriteBufPtrType WriteBytePtrType -- 2.47.1