~ubuntu-branches/ubuntu/lucid/judy/lucid

« back to all changes in this revision

Viewing changes to test/manual/timeit.h

  • Committer: Bazaar Package Importer
  • Author(s): Troy Heber
  • Date: 2005-03-22 06:55:53 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050322065553-syjpkd48r4re18dn
Tags: 1.0.1-5

* Moving LGPL link in copyright back to LGPL-2.1
* Cleanup of debian/rules: removed explicit refs to 32-bit archs, removed
  unnecessary nostrip, using --man dir to install man pages, moving from
  dh_movefiles to dh_install.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifndef _TIMEIT_H
2
 
#define _TIMEIT_H
3
 
 
4
 
// @(#) $Revision: 4.14 $ $Source: /judy/src/apps/benchmark/timeit.h $
5
 
//
6
 
// Timing and timers header file with example program.
7
 
//
8
 
// You should compile with one of these defined:
9
 
//
10
 
//   JU_HPUX_PA         # control register available (via asm()).
11
 
//   JU_HPUX_IPF        # TBD, see below.
12
 
//   JU_LINUX_IA32      # control register available (via get_cycles()).
13
 
//   JU_LINUX_IPF       # control register available (via get_cycles()).
14
 
//   JU_WIN_IA32        # uses clock().
15
 
//
16
 
// Otherwise default (low-res) timing code using gettimeofday() results.  This
17
 
// mode is only accurate to usecs, and fuzzy due to syscall overhead.
18
 
//
19
 
// Public macros; the *_HRTm() forms are much faster than the others:
20
 
//
21
 
// TIMER_vars(T) - declare variables to use for timers
22
 
// STARTTm(T)    - start the timer with variable T
23
 
// ENDTm(D,T)    - compute usec from last STARTTm(T), save result in double D
24
 
// START_HRTm(T) - high-res for short intervals (< 2^32[64] clock ticks) only
25
 
// END_HRTm(D,T) - high-res for short intervals (< 2^32[64] clock ticks) only
26
 
//
27
 
// Private macros:
28
 
//
29
 
// __START_HRTm(T) - read high-res control register, save in T
30
 
// __END_HRTm(T)   - read high-res control register, save in T
31
 
// __HRONLY(D,T)   - use high-res clock only
32
 
//
33
 
// Note:  The __*_HRTm and __HRONLY macros are only available on platforms with
34
 
// control registers for high-res clocks.  On hpux_pa this is a 32-bit register
35
 
// and gettimeofday() must be used to handle rollover; on linux_* this is a
36
 
// 64-bit register.
37
 
 
38
 
#ifndef JU_WIN_IA32
39
 
#include <sys/time.h>           // Win32 uses a whole different paradigm.
40
 
#include <unistd.h>             // for getopt(), which Win32 lacks.
41
 
#endif
42
 
 
43
 
#include <time.h>
44
 
 
45
 
// Public variables:
46
 
 
47
 
extern double USecPerClock;     // defined in timeit.c.
48
 
 
49
 
// __HRONLY is used for multiple platforms, but only in cases where there is a
50
 
// high-res clock and find_CPU_speed() is available from timeit.c:
51
 
 
52
 
#define __HRONLY(D,T)                                                   \
53
 
        {                                                               \
54
 
            if (USecPerClock == 0.0) USecPerClock = find_CPU_speed();   \
55
 
            (D) = ((double) (__stop_##T - __start_##T)) * USecPerClock; \
56
 
        }
57
 
 
58
 
 
59
 
// TIMING ROUTINES:
60
 
 
61
 
 
62
 
// ********************* HPUX PA ****************************
63
 
//
64
 
// Define __START_HRTm and __END_HRTm only, and let later common code add
65
 
// STARTTm and ENDTm.
66
 
//
67
 
// TBD:  On hpux_pa or hpux_ipf 64-bit, is CR_IT a 64-bit register?  If so, it's
68
 
// unnecessary and wasteful to use gettimeofday() later to watch for rollover.
69
 
//
70
 
// TBD:  JU_HPUX_IPF does not recognize CR_IT ("Undeclared variable 'CR_IT'"),
71
 
// so for now treat that platform as having no high-res clock and do not
72
 
// included it in this section.
73
 
 
74
 
#if (JU_HPUX_PA)
75
 
#include <machine/reg.h>
76
 
#include <sys/pstat.h>
77
 
 
78
 
double find_CPU_speed(void);
79
 
 
80
 
// Note:  On hpux_*, at least older compilers, it is neither necessary nor even
81
 
// allowed to mark the __start_* and __stop_* variables as volatile; the
82
 
// compiler does not optimize out the code even without it:
83
 
 
84
 
#define TIMER_vars(T)                                    \
85
 
        register unsigned long  __start_##T, __stop_##T; \
86
 
                 struct timeval __TVBeg_##T, __TVEnd_##T
87
 
 
88
 
#define __START_HRTm(T) _asm("MFCTL", CR_IT, __start_##T)
89
 
#define __END_HRTm(T)   _asm("MFCTL", CR_IT, __stop_##T )
90
 
 
91
 
#endif // (JU_HPUX_PA)
92
 
 
93
 
// ********************* LINUX IA32 **************************
94
 
//
95
 
#ifdef JU_LINUX_IA32
96
 
#include <asm/msr.h>
97
 
 
98
 
double find_CPU_speed(void);
99
 
 
100
 
#define TIMER_vars(T)                                    \
101
 
        register unsigned long  __start_##T, __stop_##T; \
102
 
                 struct timeval __TVBeg_##T, __TVEnd_##T
103
 
 
104
 
#define __START_HRTm(T) rdtscl(__start_##T)
105
 
#define __END_HRTm(T)   rdtscl(__stop_##T)
106
 
 
107
 
#endif // JU_LINUX_IA32
108
 
 
109
 
// ********************* LINUX_IPF **************************
110
 
//
111
 
// Define __START_HRTm and __END_HRTm, and also STARTTm and ENDTm in terms of
112
 
// the former (no need for gettimeofday()).
113
 
 
114
 
#ifdef JU_LINUX_IPF
115
 
 
116
 
#include <asm/timex.h>
117
 
 
118
 
double find_CPU_speed(void);
119
 
 
120
 
// Using cycles_t rather than unsigned long [long] should be more portable;
121
 
// and, it appears necessary to mark __start_* and __end_* as volatile so the
122
 
// gcc compiler does not optimize out the register access:
123
 
 
124
 
#define TIMER_vars(T)                                             \
125
 
        register volatile cycles_t       __start_##T, __stop_##T; \
126
 
                          struct timeval __TVBeg_##T, __TVEnd_##T
127
 
 
128
 
// This seems required for linux_ia32:
129
 
 
130
 
 
131
 
// Older code (see 4.13) used rdtscl(), but this is not portable and does not
132
 
// result in a 64-bit value, unlike get_cycles(), which apparently takes
133
 
// advantage of a 64-bit control register on both IA32 and IPF => always
134
 
// high-res timing with no rollover issues.  Note, cycles_t is unsigned, so the
135
 
// math works even in case of a rollover.
136
 
 
137
 
#define __START_HRTm(T)  __start_##T = get_cycles()
138
 
#define __END_HRTm(T)    __stop_##T  = get_cycles()
139
 
 
140
 
#define STARTTm(T)  __START_HRTm(T)
141
 
#define ENDTm(D,T)  { __END_HRTm(T); __HRONLY(D,T); }
142
 
 
143
 
#endif // JU_LINUX_IPF
144
 
 
145
 
 
146
 
// ********************* WIN IA32 *****************************
147
 
//
148
 
// WIN IA32 has no way to access the control register (?), so define STARTTm
149
 
// and ENDTm directly using clock():
150
 
 
151
 
#ifdef JU_WIN_IA32
152
 
 
153
 
clock_t TBeg, TEnd;
154
 
 
155
 
#define TIMER_vars(T)  struct timeval __TVBeg_##T, __TVEnd_##T
156
 
 
157
 
#define STARTTm(T)   __TVBeg_##T = clock()
158
 
#define ENDTm(D,T) { __TVEnd_##T = clock(); \
159
 
                     (D) = ((double) (__TVEnd_##T - __TVBeg_##T)); }
160
 
 
161
 
#endif // JU_WIN_IA32
162
 
 
163
 
 
164
 
// ********************* OTHER *****************************
165
 
//
166
 
// Default to using the low-res, slow-access clock only.
167
 
 
168
 
#ifndef TIMER_vars
169
 
 
170
 
#define TIMER_vars(T)  struct timeval __TVBeg_##T, __TVEnd_##T
171
 
 
172
 
#define STARTTm(T)  gettimeofday(&__TVBeg_##T, NULL)
173
 
 
174
 
#define ENDTm(D,T)  gettimeofday(&__TVEnd_##T, NULL);                     \
175
 
                    (D) = (((double) __TVEnd_##T.tv_sec * ((double) 1E6)) \
176
 
                          + (double) __TVEnd_##T.tv_usec)                 \
177
 
                        - (((double) __TVBeg_##T.tv_sec * ((double) 1E6)) \
178
 
                          + (double) __TVBeg_##T.tv_usec)
179
 
#endif // ! TIMER_vars
180
 
 
181
 
 
182
 
// COMMON CODE FOR SYSTEMS WITH HIGH-RES CLOCKS (CONTROL REGISTERS):
183
 
 
184
 
#ifdef __START_HRTm
185
 
 
186
 
// Platforms that define __START_HRTm but not STARTTm (presently only hpux_pa)
187
 
// use gettimeofday() for the low-res clock and __START_HRTm/__END_HRTm for
188
 
// the high-res clock.  If the low-res clock did not "roll over", use the
189
 
// high-res clock; see __HRONLY.
190
 
//
191
 
// Note:  Rollover is defined conservatively as 1E5 usec (= 1/10 sec).  This
192
 
// would require a 40 GHz 32-bit system to be violated.
193
 
 
194
 
#ifndef STARTTm
195
 
#define STARTTm(T)                                                      \
196
 
        {                                                               \
197
 
            gettimeofday(&__TVBeg_##T, NULL); __START_HRTm(T);          \
198
 
        }
199
 
 
200
 
#define ENDTm(D,T)                                                      \
201
 
        {                                                               \
202
 
            __END_HRTm(T); gettimeofday(&__TVEnd_##T, NULL);            \
203
 
                                                                        \
204
 
            (D) = (((double) __TVEnd_##T.tv_sec * ((double) 1E6))       \
205
 
                  + (double) __TVEnd_##T.tv_usec)                       \
206
 
                - (((double) __TVBeg_##T.tv_sec * ((double) 1E6))       \
207
 
                  + (double) __TVBeg_##T.tv_usec);                      \
208
 
                                                                        \
209
 
            if ((D) < 1E5) __HRONLY(D,T);                               \
210
 
        }
211
 
#endif // ! STARTTm
212
 
 
213
 
// Faster forms for heavy/frequent use in code loops where intervals are less
214
 
// than 2^32[64] clock ticks:
215
 
 
216
 
#define START_HRTm(T)  __START_HRTm(T)
217
 
#define END_HRTm(D,T)  { __END_HRTm(T); __HRONLY(D,T); }
218
 
 
219
 
#endif // __START_HRTm
220
 
 
221
 
#endif // #ifndef _TIMEIT_H