WSL/SLF GitLab Repository

Timer.cc 4.99 KB
Newer Older
1
2
/***********************************************************************************/
/*                   Copyright GridGroup, EIA-FR 2010                              */
3
/*  Copyright 2010-2013 WSL Institute for Snow and Avalanche Research  SLF-DAVOS   */
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/***********************************************************************************/
/* This file is part of MeteoIO.
    MeteoIO is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MeteoIO 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with MeteoIO.  If not, see <http://www.gnu.org/licenses/>.
*/
//AUTHORS: Tuan Anh Nguyen (original implementation in popc)
//         Mathias Bavay (port and rewrite for Alpine3D, then MeteoIO)

#include <stdio.h>
23
#ifdef WIN32
24
25
26
27
28
29
30
31
	#include <windows.h>
	#undef max
	#undef min
#else
	#include <sys/time.h>
#endif

#include "Timer.h"
32
33
34
35

namespace mio {

/**
36
* @brief Default constructor.
37
38
* Initialize internal variables. It does NOT start timing.
*/
39
40
Timer::Timer()
     : start_point(0.), elapsed(0.), isRunning(false) {}
41
42

/**
43
* @brief Start the timer.
44
45
46
*/
void Timer::start() {
	if (!isRunning) {
47
48
		isRunning = true;
		start_point = getCurrentTime();
49
50
51
52
	}
}

/**
53
54
55
56
* @brief Reset and start the timer.
*/
void Timer::restart() {
	reset();
57
	isRunning = true;
58
59
60
61
}

/**
* @brief Stop the timer.
62
* It can be restarted afterward, adding time to what was already timed.
63
64
65
*/
void Timer::stop() {
	if (isRunning) {
66
		elapsed += static_cast<double>( getCurrentTime()-start_point );
67
		isRunning = false;
68
69
70
71
72
73
74
	}
}

/**
* @brief Reset the timer to zero.
*/
void Timer::reset() {
75
	elapsed = 0.;
76
	start_point = getCurrentTime();
77
78
79
}

/**
80
* @brief Get total elapsed time.
81
* It returns the sum of all the elapsed time between all the start/stop sessions since
82
* the timer was created or the last call to reset. Time is in seconds with microsecond resolution.
83
*/
84
double Timer::getElapsed() const {
85
	if (isRunning) {
86
		return elapsed + static_cast<double>(getCurrentTime()-start_point);
87
88
89
90
	}
	return elapsed;
}

91
#ifdef WIN32
92
long double Timer::getCurrentTime() const {
93
94
95
96
97
98
99
100
101
102
	SYSTEMTIME systemTime;
	GetSystemTime( &systemTime );

	FILETIME fileTime;
	SystemTimeToFileTime( &systemTime, &fileTime );

	ULARGE_INTEGER uli;
	uli.LowPart = fileTime.dwLowDateTime;
	uli.HighPart = fileTime.dwHighDateTime;

103
	const ULONGLONG units_convert = 10000*1000ULL; //it gives the time since 1 January 1601 (UTC) in units of 100ns
104
	const ULONGLONG offset_to_epoch = 11644473600ULL; //offset in seconds to Unix epoch, 134774 days * 24*3600
105
	return static_cast<long double>(uli.QuadPart - offset_to_epoch*units_convert) / units_convert;
106
107
}
#else
108
long double Timer::getCurrentTime() const {
109
110
	timeval tp;
	gettimeofday(&tp,NULL);
111
	const long double t = static_cast<long double>(tp.tv_sec) + static_cast<long double>(tp.tv_usec)*1.e-6;
112
113
	return t;
}
114

115

116
117
118
119
120
#endif

#ifndef WIN32
const int UsageTimer::who = RUSAGE_SELF;

121
UsageTimer::UsageTimer() : start_usage(), current_usage(), user_time(0.), sys_time(0.), elapsed(0.), is_running(false) {}
122

123
void UsageTimer::start()
124
125
126
127
128
129
130
{
	if (!is_running) {
		is_running = true;
		getrusage(UsageTimer::who, &start_usage);
	}
}

131
void UsageTimer::stop()
132
133
134
135
136
137
138
{
	if (is_running) {
		getElapsedTimes();
		is_running = false;
	}
}

139
void UsageTimer::restart()
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
{
	reset();
	is_running = true;
}

void UsageTimer::reset() {
	user_time = sys_time = elapsed= 0.;
}

double UsageTimer::getElapsed()
{
	if (is_running) {
		getElapsedTimes();
	}

	return elapsed;
}

double UsageTimer::getElapsedUserTime()
{
	if (is_running) {
		getElapsedTimes();
	}

	return user_time;
}

double UsageTimer::getElapsedSystemTime()
{
	if (is_running) {
		getElapsedTimes();
	}

	return sys_time;
}

void UsageTimer::getElapsedTimes()
{
	getrusage(UsageTimer::who, &current_usage);
179

180
	//calculate start point
181
182
183
	const long double start_user_time = static_cast<long double>(start_usage.ru_utime.tv_sec) + static_cast<long double>(start_usage.ru_utime.tv_usec)*1e-6;
	const long double start_sys_time  = static_cast<long double>(start_usage.ru_stime.tv_sec) + static_cast<long double>(start_usage.ru_stime.tv_usec)*1e-6;

184
	//calculate end point
185
186
	const long double end_user_time = static_cast<long double>(current_usage.ru_utime.tv_sec) + static_cast<long double>(current_usage.ru_utime.tv_usec)*1e-6;
	const long double end_sys_time  = static_cast<long double>(current_usage.ru_stime.tv_sec) + static_cast<long double>(current_usage.ru_stime.tv_usec)*1e-6;
187
188

	//calculate different elapsed times
189
190
191
	user_time = static_cast<double>( end_user_time - start_user_time );
	sys_time = static_cast<double>( end_sys_time - start_sys_time );
	elapsed = static_cast<double>( sys_time + user_time );
192
}
193
#endif
194
195
196

} //namespace