mirror of https://github.com/postgres/postgres
counts alongside the planner's estimates. By Martijn van Oosterhout, with some further work by Tom Lane.REL7_2_STABLE
parent
27d2890b87
commit
89fa551808
@ -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; |
||||
} |
||||
@ -0,0 +1,39 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* instrument.h |
||||
* definitions for run-time statistics collection |
||||
* |
||||
* |
||||
* Copyright (c) 2001, PostgreSQL Global Development Group |
||||
* |
||||
* $Id: instrument.h,v 1.1 2001/09/18 01:59:06 tgl Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef INSTRUMENT_H |
||||
#define INSTRUMENT_H |
||||
|
||||
#include <sys/time.h> |
||||
|
||||
|
||||
typedef struct Instrumentation |
||||
{ |
||||
/* Info about current plan cycle: */ |
||||
bool running; /* TRUE if we've completed first tuple */ |
||||
struct timeval starttime; /* Start time of current iteration of node */ |
||||
struct timeval counter; /* Accumulates runtime for this node */ |
||||
double firsttuple; /* Time for first tuple of this cycle */ |
||||
double tuplecount; /* Tuples so far this cycle */ |
||||
/* Accumulated statistics across all completed cycles: */ |
||||
double startup; /* Total startup time (in seconds) */ |
||||
double total; /* Total total time (in seconds) */ |
||||
double ntuples; /* Total tuples produced */ |
||||
double nloops; /* # of run cycles for this node */ |
||||
} Instrumentation; |
||||
|
||||
extern Instrumentation *InstrAlloc(void); |
||||
extern void InstrStartNode(Instrumentation *instr); |
||||
extern void InstrStopNode(Instrumentation *instr, bool returnedTuple); |
||||
extern void InstrEndLoop(Instrumentation *instr); |
||||
|
||||
#endif /* INSTRUMENT_H */ |
||||
Loading…
Reference in new issue