1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-05 07:21:24 +03:00

EXPLAIN ANALYZE feature to measure and show actual runtimes and tuple

counts alongside the planner's estimates.  By Martijn van Oosterhout,
with some further work by Tom Lane.
This commit is contained in:
Tom Lane
2001-09-18 01:59:07 +00:00
parent 27d2890b87
commit 89fa551808
18 changed files with 413 additions and 87 deletions

View File

@ -0,0 +1,122 @@
/*-------------------------------------------------------------------------
*
* instrument.c
* functions for instrumentation of plan execution
*
*
* Copyright (c) 2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/instrument.c,v 1.1 2001/09/18 01:59:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <unistd.h>
#include "executor/instrument.h"
/* Allocate new instrumentation structure */
Instrumentation *
InstrAlloc(void)
{
Instrumentation *instr = palloc( sizeof(Instrumentation) );
memset( instr, 0, sizeof(Instrumentation) );
return instr;
}
/* Entry to a plan node */
void
InstrStartNode(Instrumentation *instr)
{
if (!instr)
return;
if (instr->starttime.tv_sec != 0 || instr->starttime.tv_usec != 0)
elog(DEBUG, "InstrStartTimer called twice in a row");
else
gettimeofday(&instr->starttime, NULL);
}
/* Exit from a plan node */
void
InstrStopNode(Instrumentation *instr, bool returnedTuple)
{
struct timeval endtime;
if (!instr)
return;
if (instr->starttime.tv_sec == 0 && instr->starttime.tv_usec == 0)
{
elog(DEBUG, "InstrStopNode without start");
return;
}
gettimeofday(&endtime, NULL);
instr->counter.tv_sec += endtime.tv_sec - instr->starttime.tv_sec;
instr->counter.tv_usec += endtime.tv_usec - instr->starttime.tv_usec;
/* Normalize after each add to avoid overflow/underflow of tv_usec */
while (instr->counter.tv_usec < 0)
{
instr->counter.tv_usec += 1000000;
instr->counter.tv_sec--;
}
while (instr->counter.tv_usec >= 1000000)
{
instr->counter.tv_usec -= 1000000;
instr->counter.tv_sec++;
}
instr->starttime.tv_sec = 0;
instr->starttime.tv_usec = 0;
/* Is this the first tuple of this cycle? */
if (!instr->running)
{
instr->running = true;
instr->firsttuple = (double) instr->counter.tv_sec +
(double) instr->counter.tv_usec / 1000000.0;
}
if (returnedTuple)
instr->tuplecount += 1;
}
/* Finish a run cycle for a plan node */
void
InstrEndLoop(Instrumentation *instr)
{
double totaltime;
if (!instr)
return;
/* Skip if nothing has happened, or already shut down */
if (!instr->running)
return;
/* Accumulate statistics */
totaltime = (double) instr->counter.tv_sec +
(double) instr->counter.tv_usec / 1000000.0;
instr->startup += instr->firsttuple;
instr->total += totaltime;
instr->ntuples += instr->tuplecount;
instr->nloops += 1;
/* Reset for next cycle (if any) */
instr->running = false;
instr->starttime.tv_sec = 0;
instr->starttime.tv_usec = 0;
instr->counter.tv_sec = 0;
instr->counter.tv_usec = 0;
instr->firsttuple = 0;
instr->tuplecount = 0;
}