Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "postgres.h"
00015
00016 #include <unistd.h>
00017
00018 #include "executor/instrument.h"
00019
00020 BufferUsage pgBufferUsage;
00021
00022 static void BufferUsageAccumDiff(BufferUsage *dst,
00023 const BufferUsage *add, const BufferUsage *sub);
00024
00025
00026
00027 Instrumentation *
00028 InstrAlloc(int n, int instrument_options)
00029 {
00030 Instrumentation *instr;
00031
00032
00033 instr = palloc0(n * sizeof(Instrumentation));
00034 if (instrument_options & (INSTRUMENT_BUFFERS | INSTRUMENT_TIMER))
00035 {
00036 bool need_buffers = (instrument_options & INSTRUMENT_BUFFERS) != 0;
00037 bool need_timer = (instrument_options & INSTRUMENT_TIMER) != 0;
00038 int i;
00039
00040 for (i = 0; i < n; i++)
00041 {
00042 instr[i].need_bufusage = need_buffers;
00043 instr[i].need_timer = need_timer;
00044 }
00045 }
00046
00047 return instr;
00048 }
00049
00050
00051 void
00052 InstrStartNode(Instrumentation *instr)
00053 {
00054 if (instr->need_timer)
00055 {
00056 if (INSTR_TIME_IS_ZERO(instr->starttime))
00057 INSTR_TIME_SET_CURRENT(instr->starttime);
00058 else
00059 elog(ERROR, "InstrStartNode called twice in a row");
00060 }
00061
00062
00063 if (instr->need_bufusage)
00064 instr->bufusage_start = pgBufferUsage;
00065 }
00066
00067
00068 void
00069 InstrStopNode(Instrumentation *instr, double nTuples)
00070 {
00071 instr_time endtime;
00072
00073
00074 instr->tuplecount += nTuples;
00075
00076
00077 if (instr->need_timer)
00078 {
00079 if (INSTR_TIME_IS_ZERO(instr->starttime))
00080 elog(ERROR, "InstrStopNode called without start");
00081
00082 INSTR_TIME_SET_CURRENT(endtime);
00083 INSTR_TIME_ACCUM_DIFF(instr->counter, endtime, instr->starttime);
00084
00085 INSTR_TIME_SET_ZERO(instr->starttime);
00086 }
00087
00088
00089 if (instr->need_bufusage)
00090 BufferUsageAccumDiff(&instr->bufusage,
00091 &pgBufferUsage, &instr->bufusage_start);
00092
00093
00094 if (!instr->running)
00095 {
00096 instr->running = true;
00097 instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
00098 }
00099 }
00100
00101
00102 void
00103 InstrEndLoop(Instrumentation *instr)
00104 {
00105 double totaltime;
00106
00107
00108 if (!instr->running)
00109 return;
00110
00111 if (!INSTR_TIME_IS_ZERO(instr->starttime))
00112 elog(ERROR, "InstrEndLoop called on running node");
00113
00114
00115 totaltime = INSTR_TIME_GET_DOUBLE(instr->counter);
00116
00117 instr->startup += instr->firsttuple;
00118 instr->total += totaltime;
00119 instr->ntuples += instr->tuplecount;
00120 instr->nloops += 1;
00121
00122
00123 instr->running = false;
00124 INSTR_TIME_SET_ZERO(instr->starttime);
00125 INSTR_TIME_SET_ZERO(instr->counter);
00126 instr->firsttuple = 0;
00127 instr->tuplecount = 0;
00128 }
00129
00130
00131 static void
00132 BufferUsageAccumDiff(BufferUsage *dst,
00133 const BufferUsage *add,
00134 const BufferUsage *sub)
00135 {
00136 dst->shared_blks_hit += add->shared_blks_hit - sub->shared_blks_hit;
00137 dst->shared_blks_read += add->shared_blks_read - sub->shared_blks_read;
00138 dst->shared_blks_dirtied += add->shared_blks_dirtied - sub->shared_blks_dirtied;
00139 dst->shared_blks_written += add->shared_blks_written - sub->shared_blks_written;
00140 dst->local_blks_hit += add->local_blks_hit - sub->local_blks_hit;
00141 dst->local_blks_read += add->local_blks_read - sub->local_blks_read;
00142 dst->local_blks_dirtied += add->local_blks_dirtied - sub->local_blks_dirtied;
00143 dst->local_blks_written += add->local_blks_written - sub->local_blks_written;
00144 dst->temp_blks_read += add->temp_blks_read - sub->temp_blks_read;
00145 dst->temp_blks_written += add->temp_blks_written - sub->temp_blks_written;
00146 INSTR_TIME_ACCUM_DIFF(dst->blk_read_time,
00147 add->blk_read_time, sub->blk_read_time);
00148 INSTR_TIME_ACCUM_DIFF(dst->blk_write_time,
00149 add->blk_write_time, sub->blk_write_time);
00150 }