1
// @(#) $Revision: 4.12 $ $Source: /judy/judy/src/apps/benchmark/timeit.c,v $
5
// YOU MUST COMPILE THIS WITH ONE OF THESE DEFINED:
13
// If NONE of these are defined, this whole code section is ifdef'd out to
14
// avoid compile/link errors due to usage here of objects not defined in
15
// timeit.h. See end of file.
17
// TBD: Improve on this; possibly it's OK now not to ifdef this out, and get
18
// default, low-res timing behavior; see timeit.h.
20
// Compile with -D_TIMEIT_TEST to include a main program for testing; see
23
#if (JU_HPUX_PA || JU_LINUX_IA32 || JU_LINUX_IPF)
24
#define _TIMEIT_HIGHRES
27
#ifdef _TIMEIT_HIGHRES
29
#include <sys/time.h> // Win32 uses a whole different paradigm.
30
#include <unistd.h> // for getopt(), which Win32 lacks.
34
double USecPerClock; // usec per control register count.
37
// ****************************************************************************
38
// F I N D C P U S P E E D
40
// Return microseconds per control/timer register count. Examples:
42
// 0.002 for 500 MHz processor
43
// 0.001 for 1 GHz processor
45
double find_CPU_speed(void)
47
double DeltaUSec; // Timing result in uSec.
48
TIMER_vars(tm); // creates __TVBeg_tm, ...
49
// (used for consistency with __START_HRTm)
51
gettimeofday(&__TVBeg_tm, NULL); // get low-res time.
52
__START_HRTm(tm); // get __start_tm (high-res).
53
sleep(1); // time passes; 1 sec suffices.
54
__END_HRTm(tm); // get __stop_tm (high-res).
55
gettimeofday(&__TVEnd_tm, NULL); // get low-res time.
57
// gettimeofday() returns usec; compute elapsed time:
59
DeltaUSec = (((double) __TVEnd_tm.tv_sec * ((double) 1E6))
60
+ (double) __TVEnd_tm.tv_usec)
61
- (((double) __TVBeg_tm.tv_sec * ((double) 1E6))
62
+ (double) __TVBeg_tm.tv_usec);
64
// Control register returns ticks, and the ratio can now be computed:
66
return (DeltaUSec / ((double) (__stop_tm - __start_tm)));
70
#else // _TIMEIT_HIGHRES
71
void dummy() {} // avoid "empty source file" warnings when no _TIMEIT_TEST.
75
// ****************************************************************************
77
// Ifdef the test main() separately, including #includes, for platforms that do
78
// not define find_CPU_speed() above.
82
#include <sys/time.h> // Win32 uses a whole different paradigm.
83
#include <unistd.h> // for getopt(), which Win32 lacks.
88
//#include <values.h> // for MAXDOUBLE
89
#define MAXDOUBLE (10e99)
93
// ****************************************************************************
96
// Example code for timeit:
98
// To compile and test this program on HP-UX, run the next lines as commands.
100
// cc -Wl,-a,archive -DJU_HPUX_PA -D__HPUX__ -D_TIMEIT_TEST -o timeit timeit.c
101
// timeit # run test program.
102
// rm -f timeit # clean up after test.
104
int main(int argc, char **argv)
106
int i = 0; // loop index.
107
long i_max = 10; // number of loops.
108
int preload = 1; // loops to throw away (preload cache).
109
double ztime; // timer overhead.
110
double usec[4]; // for early timing tests.
111
double DeltaUSec; // timing result in usec.
112
double prevtime; // from previous loop.
113
double mintime; // minimum event time.
114
struct timeval tmjunk; // for throw-away syscall.
115
TIMER_vars(tm1); // overall timer variables.
116
TIMER_vars(tm2); // misc + loop timer variables.
121
STARTTm(tm1); // whole program timer.
125
// The first arg is the number of iterations (default is i_max):
129
i = atoi(argv[1]) + preload;
130
if (i > 0) i_max = (long)i;
133
// Calculate timer overhead (ztime):
135
#ifdef _TIMEIT_HIGHRES
136
(void) puts("Possible slight delay here due to find_CPU_speed()...");
138
(void) puts("No high-res clock or find_CPU_speed() for this platform.");
143
for (i = 0; i < 100; ++i) // average many runs.
146
ENDTm(DeltaUSec, tm2);
149
ztime = ztime / ((double) i);
152
// SIMPLE TESTS OF TIMER OVERHEAD:
154
// Make two passes at both the high-res (if any) and slower timers.
156
(void) puts("\nTiming timers themselves: start, end, end");
158
#define PRINTPASS(Desc,Pass) \
159
(void) printf("%-8s pass %d: %f - %f = %f usec\n", Desc, Pass, \
160
usec[((Pass) * 2) - 1], usec[((Pass) * 2) - 2], \
161
usec[((Pass) * 2) - 1] - usec[((Pass) * 2) - 2])
163
#ifdef _TIMEIT_HIGHRES
165
END_HRTm(usec[0], tm2); // throw away in case of sleep(1) here.
168
END_HRTm(usec[0], tm2);
169
END_HRTm(usec[1], tm2);
172
END_HRTm(usec[2], tm2);
173
END_HRTm(usec[3], tm2);
175
PRINTPASS("High-res", 1);
176
PRINTPASS("High-res", 2);
180
ENDTm(usec[0], tm2); // throw away in case of sleep(1) here.
190
PRINTPASS("Non-HR", 1);
191
PRINTPASS("Non-HR", 2);
194
// PRINT INITIAL INFO:
196
#ifdef _TIMEIT_HIGHRES
198
// Print the CPU speed:
200
// Note: USecPerClock is a global set by the first instance of STARTTm. You
201
// can also get this number by calling find_CPU_speed().
203
(void) printf("\nClock step = %.3f nsec => %.1f MHz.\n",
204
USecPerClock * 1000.0, 1.0 / USecPerClock);
207
// Print timer overhead even though it's been subtracted from the reported
210
(void) printf("Timer overhead subtracted from the times below = %f "
214
// DO A FAST TIMER CHECK:
216
(void) puts("\nCheck timer precision by repeating the same action:");
217
(void) puts("Times in each group should be close together.");
218
(void) puts("\nTiming something very fast: \"++i\":");
222
for (i = 1; i <= i_max; ++i)
224
prevtime = DeltaUSec;
225
STARTTm(tm2); // start the timer.
226
++i; // statement to time.
227
ENDTm(DeltaUSec, tm2); // stop the timer.
228
DeltaUSec -= ztime; // remove timer overhead.
230
// Throw away the first loop iteration to warm up the cache:
234
if (mintime == MAXDOUBLE) mintime = DeltaUSec;
236
(void) printf("%3d. %8.3f nanosec,\tmintime diff %8.1f %%\n",
237
i - preload, DeltaUSec * 1000.0,
238
((DeltaUSec - mintime) * 100) / mintime);
240
if (DeltaUSec < mintime) mintime = DeltaUSec;
245
// TIME A FUNCTION CALL:
247
(void) puts("\nTiming a function: \"gettimeofday()\":");
250
for (i = 1; i <= i_max; ++i)
252
prevtime = DeltaUSec;
253
STARTTm(tm2); // start the timer.
254
gettimeofday(&tmjunk, NULL); // burn some cycles.
255
ENDTm(DeltaUSec, tm2); // stop the timer.
256
DeltaUSec -= ztime; // remove timer overhead.
258
// Throw away the first loop iteration to warm up the cache:
262
if (mintime == MAXDOUBLE) mintime = DeltaUSec;
264
(void) printf("%3d. %8.3f usec,\tmintime diff %8.1f %%\n",
265
i - preload, DeltaUSec,
266
((DeltaUSec - mintime) * 100) / mintime);
268
if (DeltaUSec < mintime) mintime = DeltaUSec;
273
// TIME SOMETHING SLOW:
275
(void) puts("\nTiming something slow: \"sleep(1)\":");
278
for (i = 1; i <= i_max; ++i)
280
prevtime = DeltaUSec;
281
STARTTm(tm2); // start the timer.
283
ENDTm(DeltaUSec, tm2); // stop the timer.
284
DeltaUSec -= ztime; // remove timer overhead.
286
// Throw away the first loop iteration to warm up the cache:
290
if (mintime == MAXDOUBLE) mintime = DeltaUSec;
292
(void) printf("%3d. %8.3f sec,\tmintime diff %8.1f %%\n",
293
i - preload, DeltaUSec/1E6,
294
((DeltaUSec - mintime) * 100) / mintime);
296
if (DeltaUSec < mintime) mintime = DeltaUSec;
303
// Print program execution time:
305
ENDTm(DeltaUSec, tm1);
306
(void) printf("\nProgram execution time: %.3f sec\n", DeltaUSec / 1E6);
311
#endif // #ifdef _TIMEIT_TEST