forked from jkriege2/TinyTIFF
-
Notifications
You must be signed in to change notification settings - Fork 1
/
tinytiffhighrestimer.h
190 lines (163 loc) · 8.12 KB
/
tinytiffhighrestimer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*
Copyright (c) 2008-2015 Jan W. Krieger (<[email protected]>, <[email protected]>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
last modification: $LastChangedDate: 2015-07-07 12:07:58 +0200 (Di, 07 Jul 2015) $ (revision $Rev: 4005 $)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \defgroup highrestimer_group High Resolution Timer
* \ingroup tools
*
* This group contains a class that implements a high-resolution timer. Note that this
* is highly system-dependent and you will find a way to implement this on your OS!
*/
/*@{*/
/** \file highrestimer.h
* \ingroup highrestimer_group
*/
#include <cmath>
#include <cstdlib>
#include <iostream>
#ifndef __WINDOWS__
# if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)
# define __WINDOWS__
# endif
#endif
#ifndef __LINUX__
# if defined(linux)
# define __LINUX__
# endif
#endif
#ifndef __WINDOWS__
# ifndef __LINUX__
# warning("these methods are ment to be used under windows or linux ... no other system were tested")
# endif
#endif
#if defined(__WINDOWS__)
#include<windows.h>
#elif defined(__LINUX__)
#include <sys/time.h>
#else
#warning("your operating system is not supported: you will have to implement this on your systems")
#include <sys/time.h>
#endif
#ifndef TINYTIFHIGHRESTIMER_H
#define TINYTIFHIGHRESTIMER_H
/**
* \brief This class implements a high resolution timer capable of measuring time intervals with a resolution
* of some microseconds
* \ingroup highrestimer_group
*
* \attention Note that this is a MS Windows specific implementation od a high-resolution timer using some of
* windows' API methods (namely \c QueryPerformanceCounter() and \c QueryPerformanceFrequency() ). So if you want
* to use this class on non-win32 systems you will have to find a way to implement it for your system!!!
*
* \attention Also note that a standard windows system is NOT a real time OS. So do not expect to get a high accuracy
* when timing operations using this timer. It gives you an accurate time stamp, but it can not guarantee when
* the code is executed!
*
*
* The timer works very simple:
* - you can start the timer with start() which means you set a time=0
* - then you can query the time difference to the last call of start() by using get_time().
* .
*
* There is also a test method test() which will try to give you a feel for the performance of the timer in
* a simple application on your computer.
* It simply does some thousand iterations and records the time needed for each single iteration. Then it may
* calculate a histogram, a mean value and a standard deviation from these times.
*
* This is the result of test() on a WinXP system, Athlon64 X2 3800+ (2GHz):
* \image html highrestimer.png
* Note that this histogram tells you more about how your system works than about the timer itself.
* What we can find out about the timer is that it really provides a resolution in the microsecond region. This can
* be seen, as there is a non-zero minimal measured interval (1.67619 usec). This basically tells us the run-time of
* the measurement loop. There are also bigger run-times which are produced, as this program ran on a multi-process
* (not process<b>or</b> !!!) OS, which means that the current process may be stalled to allow othe rprocesses to
* execute. If this would run on a single-process system we should only get one run-time, if we assume that all
* methods need a fixed amount of time. So we can use this method to test whether our system provides a sufficiently
* accurate time. The 1.68 usec give an upper bound for the timer interval and thus the resolution they do <b>not</b>
* represent the timer resolution. To get this nominal resolution in a windows system you could use the WinAPI method
* \c QueryPerformanceFrequency() which is used in the method get_time(). On my system the timer frequency is 3.57955 MHz
* which corresponds to a resolution of 0.2794 usec.
*
* \par win32 implementation issues:
* To implement this timer on windows systems I use two API calls from the windows kernel. They are:
* - <a href="http://msdn2.microsoft.com/en-us/library/ms644904.aspx">QueryPerformanceCounter()</a>
* - <a href="http://msdn2.microsoft.com/en-us/library/ms644905.aspx">QueryPerformanceFrequency()</a>
* .
* \n
* The first one is used to read times: In the start() method we simply save the current counter value to a variable.
* In get_time() we can then again use QueryPerformanceCounter() to get the current counter value and then calculate
* the difference between these two. Using QueryPerformanceFrequency() we can calculate the time difference in usecs
* from the counter value difference using:
* \f[ \Delta t=\frac{N_{\mbox{now}}-N_{\mbox{start}}}{\mbox{\texttt{QueryPerformanceFrequency()}}}\cdot 10^{6} \f]
*
* \par why not standard POSIX?
* The standard POSIX time functions available in a MinGW environment have a resolution that is in the range of
* some 10 milliseconds. This may be enough for many purposes, but for exact time measurement, as you will want
* to do it on measurement and control systems this is not sufficient. So I tried to find a possibility to
* implement a system-independent high-resolution timer. As most timer stuff depends on very low-level kernel
* calls on every operating system this seems to be nearly impossible. So I implemented this timer for win32 only,
* as this is the system we use in the lab.
*
* \par linux implementation possibility:
* This class does not implement a timer for Linux/Unix systems but I
* will provide you with a small hint how you could implement one here:
* The <a href="http://www.gnu.org/software/libc/manual/html_node/High_002dResolution-Calendar.html">\c gettimeofday()
* method</a> from the libc seems to have enough tim resolution for our pourposes, so try to use this for the high-
* resolution timer. As mentioned above this method is not available for MinGW in win32 which is the main development
* platform for this project.
*
* \test you can find an example application in the file \link test_hrestimer.cpp .
*
*/
class HighResTimer {
protected:
#ifdef __WINDOWS__
/** \brief internal: time stamp of the last call of start() */
LARGE_INTEGER last;
/** \brief internal: timer frequency */
double freq;
#else
struct timeval last;
#endif
public:
/** \brief class constructor. */
HighResTimer();
/** \brief class destructor */
~HighResTimer();
/** \brief start the timer */
void start();
/** \brief get the time since the last call of start() in microseconds */
double get_time();
/** \brief test the resolution
*
* mean value and standard deviation of 1000000 timer polls will be evaluated and returned in \c mean
* and \c stddev. If you supply \c histogram with a pointer to a memory array with \c histogram_size
* items this will hold afterwards a histogram of the data. \c histogram_x wil contain the time interval
* values of the histogram bins in \c histogram.
*
* To measure the resolution this method uses this code:
* \code
double l=get_time(), n;
for (unsigned long i=0; i<runs; i++) {
n=get_time();
h[i]=n-l;
l=n;
}
\endcode
*
*/
void test(double* mean, double* stddev, unsigned long* histogram=NULL, double* histogram_x=NULL, unsigned long histogram_size=0);
};
#endif // TINYTIFHIGHRESTIMER_H
/*@}*/