~ubuntu-branches/ubuntu/trusty/judy/trusty

« back to all changes in this revision

Viewing changes to test/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