77 * Copyright (c) 2001-2006, PostgreSQL Global Development Group
88 *
99 * IDENTIFICATION
10- * $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.16 2006/05/30 19:24:25 tgl Exp $
10+ * $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.17 2006/06/07 18:49:03 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
4242 *
4343 * The actual sampling interval is randomized with the SampleFunc() value
4444 * as the mean; this hopefully will reduce any measurement bias due to
45- *cyclic variation in the node execution time.
45+ * variation in the node execution time.
4646 */
4747#ifdef HAVE_CBRT
4848#define SampleFunc (niters ) cbrt(niters)
5656/*
5757 * We sample at every node iteration until we've reached this threshold,
5858 * so that nodes not called a large number of times are completely accurate.
59- * (Perhaps this should be a GUC variable? But beware of messing up
60- * CalculateSampleOverhead if value is too small.)
59+ * (Perhaps this should be a GUC variable?)
6160 */
6261#define SAMPLE_THRESHOLD 50
6362
@@ -71,7 +70,6 @@ static bool SampleOverheadCalculated = false;
7170static void
7271CalculateSampleOverhead (void )
7372{
74- Instrumentation instr ;
7573int i ;
7674
7775/*
@@ -82,20 +80,20 @@ CalculateSampleOverhead(void)
8280
8381for (i = 0 ;i < 5 ;i ++ )
8482{
83+ Instrumentation timer ;
84+ instr_time tmptime ;
8585int j ;
8686double overhead ;
8787
88- memset (& instr ,0 ,sizeof (instr ));
89- /*
90- * We know that samples will actually be taken up to SAMPLE_THRESHOLD,
91- * so that's as far as we can test.
92- */
93- for (j = 0 ;j < SAMPLE_THRESHOLD ;j ++ )
88+ memset (& timer ,0 ,sizeof (timer ));
89+ InstrStartNode (& timer );
90+ #define TEST_COUNT 100
91+ for (j = 0 ;j < TEST_COUNT ;j ++ )
9492{
95- InstrStartNode (& instr );
96- InstrStopNode (& instr ,1 );
93+ INSTR_TIME_SET_CURRENT (tmptime );
9794}
98- overhead = INSTR_TIME_GET_DOUBLE (instr .counter ) /instr .samplecount ;
95+ InstrStopNode (& timer ,1 );
96+ overhead = INSTR_TIME_GET_DOUBLE (timer .counter ) /TEST_COUNT ;
9997if (overhead < SampleOverhead )
10098SampleOverhead = overhead ;
10199}
@@ -159,14 +157,20 @@ InstrStopNode(Instrumentation *instr, double nTuples)
159157{
160158instr_time endtime ;
161159
160+ /*
161+ * To be sure that SampleOverhead accurately reflects the extra
162+ * overhead, we must do INSTR_TIME_SET_CURRENT() as the *first*
163+ * action that is different between the sampling and non-sampling
164+ * code paths.
165+ */
166+ INSTR_TIME_SET_CURRENT (endtime );
167+
162168if (INSTR_TIME_IS_ZERO (instr -> starttime ))
163169{
164170elog (DEBUG2 ,"InstrStopNode called without start" );
165171return ;
166172}
167173
168- INSTR_TIME_SET_CURRENT (endtime );
169-
170174#ifndef WIN32
171175instr -> counter .tv_sec += endtime .tv_sec - instr -> starttime .tv_sec ;
172176instr -> counter .tv_usec += endtime .tv_usec - instr -> starttime .tv_usec ;