1 /*
2 % Copyright (C) 2003-2020 GraphicsMagick Group
3 % Copyright (C) 2002 ImageMagick Studio
4 %
5 % This program is covered by multiple licenses, which are described in
6 % Copyright.txt. You should have received a copy of Copyright.txt with this
7 % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
8 %
9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10 % %
11 % %
12 % %
13 % TTTTT IIIII M M EEEEE RRRR %
14 % T I MM MM E R R %
15 % T I M M M EEE RRRR %
16 % T I M M E R R %
17 % T IIIII M M EEEEE R R %
18 % %
19 % %
20 % GraphicsMagick Timing Methods %
21 % %
22 % %
23 % Software Design %
24 % John Cristy %
25 % January 1993 %
26 % %
27 % %
28 % %
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
30 %
31 % Contributed by Bill Radcliffe and Bob Friesenhahn.
32 %
33 */
34
35 /*
36 Include declarations.
37 */
38 #include "magick/studio.h"
39
40 /*
41 Define declarations.
42 */
43 #if !defined(CLK_TCK)
44 # define CLK_TCK sysconf(_SC_CLK_TCK)
45 #endif
46 #if defined(HAVE_CLOCK_GETTIME)
47 # define NANOSECONDS_PER_SECOND 1000000000.0
48 # if defined(CLOCK_HIGHRES) /* Solaris */
49 # define CLOCK_ID CLOCK_HIGHRES
50 # elif defined(CLOCK_MONOTONIC_RAW) /* Linux */
51 # define CLOCK_ID CLOCK_MONOTONIC_RAW
52 # elif defined(CLOCK_MONOTONIC_PRECISE) /* FreeBSD */
53 # define CLOCK_ID CLOCK_MONOTONIC_PRECISE
54 # elif defined(CLOCK_MONOTONIC) /* Linux & FreeBSD */
55 # define CLOCK_ID CLOCK_MONOTONIC
56 # else
57 # define CLOCK_ID CLOCK_REALTIME /* Fallback */
58 # endif
59 #endif
60
61 /*
62 Forward declarations.
63 */
64 static double
65 UserTime(void);
66
67 /*
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 % %
70 % %
71 % %
72 % C o n t i n u e T i m e r %
73 % %
74 % %
75 % %
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 %
78 % Method ContinueTimer resumes a stopped stopwatch. The stopwatch continues
79 % counting from the last StartTimer() onwards.
80 %
81 % The format of the ContinueTimer method is:
82 %
83 % unsigned int ContinueTimer(TimerInfo *time_info)
84 %
85 % A description of each parameter follows.
86 %
87 % o time_info: Time statistics structure.
88 %
89 */
ContinueTimer(TimerInfo * time_info)90 MagickExport unsigned int ContinueTimer(TimerInfo *time_info)
91 {
92 assert(time_info != (TimerInfo *) NULL);
93 assert(time_info->signature == MagickSignature);
94 if (time_info->state == UndefinedTimerState)
95 return(False);
96 if (time_info->state == StoppedTimerState)
97 {
98 time_info->user.total-=time_info->user.stop-time_info->user.start;
99 time_info->elapsed.total-=
100 time_info->elapsed.stop-time_info->elapsed.start;
101 }
102 time_info->state=RunningTimerState;
103 return(True);
104 }
105
106 /*
107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108 % %
109 % %
110 % %
111 + E l a p s e d T i m e %
112 % %
113 % %
114 % %
115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116 %
117 % Method ElapsedTime returns the elapsed time (in seconds) since the last
118 % call to StartTimer().
119 %
120 % The format of the ElapsedTime method is:
121 %
122 % double ElapsedTime()
123 %
124 */
ElapsedTime(void)125 static double ElapsedTime(void)
126 {
127 #if defined(HAVE_CLOCK_GETTIME)
128 struct timespec timer;
129 (void) clock_gettime(CLOCK_ID, &timer);
130
131 return((double) timer.tv_sec + timer.tv_nsec/NANOSECONDS_PER_SECOND);
132 #elif defined(HAVE_TIMES)
133 struct tms
134 timer;
135
136 return((double) times(&timer)/CLK_TCK);
137 #else
138 #if defined(MSWINDOWS)
139 return(NTElapsedTime());
140 #else
141 return((double) clock()/CLK_TCK);
142 #endif
143 #endif
144 }
145
146 /*
147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148 % %
149 % %
150 % %
151 % G e t E l a p s e d T i m e %
152 % %
153 % %
154 % %
155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156 %
157 % Method GetElapsedTime returns the elapsed time (in seconds) passed between
158 % the start and stop events. If the stopwatch is still running, it is stopped
159 % first.
160 %
161 % The format of the GetElapsedTime method is:
162 %
163 % double GetElapsedTime(TimerInfo *time_info)
164 %
165 % A description of each parameter follows.
166 %
167 % o time_info: Timer statistics structure.
168 %
169 */
GetElapsedTime(TimerInfo * time_info)170 MagickExport double GetElapsedTime(TimerInfo *time_info)
171 {
172 assert(time_info != (TimerInfo *) NULL);
173 assert(time_info->signature == MagickSignature);
174 if (time_info->state == UndefinedTimerState)
175 return(0.0);
176 if (time_info->state == RunningTimerState)
177 StopTimer(time_info);
178 return(time_info->elapsed.total);
179 }
180
181 /*
182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183 % %
184 % %
185 % %
186 % G e t T i m e r I n f o %
187 % %
188 % %
189 % %
190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191 %
192 % Method GetTimerInfo initializes the TimerInfo structure.
193 %
194 % The format of the GetTimerInfo method is:
195 %
196 % void GetTimerInfo(TimerInfo *time_info)
197 %
198 % A description of each parameter follows.
199 %
200 % o time_info: Timer statistics structure.
201 %
202 */
GetTimerInfo(TimerInfo * time_info)203 MagickExport void GetTimerInfo(TimerInfo *time_info)
204 {
205 /*
206 Create a stopwatch and start it.
207 */
208 assert(time_info != (TimerInfo *) NULL);
209 (void) memset(time_info,0,sizeof(TimerInfo));
210 time_info->state=UndefinedTimerState;
211 time_info->signature=MagickSignature;
212 StartTimer(time_info,True);
213 }
214
215 /*
216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217 % %
218 % %
219 % %
220 % G e t T i m e r R e s o l u t i o n %
221 % %
222 % %
223 % %
224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225 %
226 % Obtain the measurement resolution of the timer.
227 %
228 % The format of the GetTimerResolution method is:
229 %
230 % void GetTimerInfo(TimerInfo *time_info)
231 %
232 % A description of each parameter follows.
233 %
234 % o time_info: Timer statistics structure.
235 %
236 */
GetTimerResolution(void)237 MagickExport double GetTimerResolution(void)
238 {
239 #if defined(HAVE_CLOCK_GETRES)
240 struct timespec timer;
241 (void) clock_getres(CLOCK_ID, &timer);
242
243 return((double) timer.tv_sec + (double) timer.tv_nsec/NANOSECONDS_PER_SECOND);
244 #elif defined(MSWINDOWS)
245 return (0.02);
246 #else
247 return (1.0/CLK_TCK);
248 #endif
249 }
250
251 /*
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 % %
254 % %
255 % %
256 % G e t U s e r T i m e %
257 % %
258 % %
259 % %
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 %
262 % Method GetUserTime returns the User time (user and system) by the operating
263 % system (in seconds) between the start and stop events. If the stopwatch is
264 % still running, it is stopped first.
265 %
266 % The format of the GetUserTime method is:
267 %
268 % double GetUserTime(TimerInfo *time_info)
269 %
270 % A description of each parameter follows.
271 %
272 % o time_info: Timer statistics structure.
273 %
274 */
GetUserTime(TimerInfo * time_info)275 MagickExport double GetUserTime(TimerInfo *time_info)
276 {
277 assert(time_info != (TimerInfo *) NULL);
278 assert(time_info->signature == MagickSignature);
279 if (time_info->state == UndefinedTimerState)
280 return(0.0);
281 if (time_info->state == RunningTimerState)
282 StopTimer(time_info);
283 return(time_info->user.total);
284 }
285
286 /*
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 % %
289 % %
290 % %
291 % R e s e t T i m e r %
292 % %
293 % %
294 % %
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 %
297 % Method ResetTimer resets the stopwatch.
298 %
299 % The format of the ResetTimer method is:
300 %
301 % void ResetTimer(TimerInfo *time_info)
302 %
303 % A description of each parameter follows.
304 %
305 % o time_info: Timer statistics structure.
306 %
307 */
ResetTimer(TimerInfo * time_info)308 MagickExport void ResetTimer(TimerInfo *time_info)
309 {
310 assert(time_info != (TimerInfo *) NULL);
311 assert(time_info->signature == MagickSignature);
312 StopTimer(time_info);
313 time_info->elapsed.stop=0.0;
314 time_info->user.stop=0.0;
315 }
316
317 /*
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319 % %
320 % %
321 % %
322 + S t a r t T i m e r %
323 % %
324 % %
325 % %
326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327 %
328 % Method StartTimer starts the stopwatch.
329 %
330 % The format of the StartTimer method is:
331 %
332 % void StartTimer(TimerInfo *time_info,const unsigned int reset)
333 %
334 % A description of each parameter follows.
335 %
336 % o time_info: Timer statistics structure.
337 %
338 % o reset: If reset is True, then the stopwatch is reset prior to starting.
339 % If reset is False, then timing is continued without resetting the
340 % stopwatch.
341 %
342 */
StartTimer(TimerInfo * time_info,const unsigned int reset)343 MagickExport void StartTimer(TimerInfo *time_info,const unsigned int reset)
344 {
345 assert(time_info != (TimerInfo *) NULL);
346 assert(time_info->signature == MagickSignature);
347 if (reset)
348 {
349 /*
350 Reset the stopwatch before starting it.
351 */
352 time_info->user.total=0.0;
353 time_info->elapsed.total=0.0;
354 }
355 if (time_info->state != RunningTimerState)
356 {
357 time_info->elapsed.start=ElapsedTime();
358 time_info->user.start=UserTime();
359 }
360 time_info->state=RunningTimerState;
361 }
362
363 /*
364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365 % %
366 % %
367 % %
368 + S t o p T i m e r %
369 % %
370 % %
371 % %
372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373 %
374 % Method StopTimer stops the stopwatch.
375 %
376 % The format of the StopTimer method is:
377 %
378 % void StopTimer(TimerInfo *time_info)
379 %
380 % A description of each parameter follows.
381 %
382 % o time_info: Timer statistics structure.
383 %
384 */
StopTimer(TimerInfo * time_info)385 MagickExport void StopTimer(TimerInfo *time_info)
386 {
387 assert(time_info != (TimerInfo *) NULL);
388 assert(time_info->signature == MagickSignature);
389 time_info->elapsed.stop=ElapsedTime();
390 time_info->user.stop=UserTime();
391 if (time_info->state == RunningTimerState)
392 {
393 time_info->user.total+=
394 time_info->user.stop-time_info->user.start+MagickEpsilon;
395 time_info->elapsed.total+=
396 time_info->elapsed.stop-time_info->elapsed.start+MagickEpsilon;
397 }
398 time_info->state=StoppedTimerState;
399 }
400
401 /*
402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
403 % %
404 % %
405 % %
406 + U s e r T i m e %
407 % %
408 % %
409 % %
410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 %
412 % Method UserTime returns the total time the process has been scheduled (in
413 % seconds) since the last call to StartTimer().
414 %
415 % The format of the UserTime method is:
416 %
417 % double UserTime()
418 %
419 */
UserTime(void)420 static double UserTime(void)
421 {
422 #if defined(HAVE_TIMES)
423 struct tms
424 timer;
425
426 (void) times(&timer);
427 return((double) (timer.tms_utime+timer.tms_stime)/CLK_TCK);
428 #else
429 #if defined(MSWINDOWS)
430 return(NTUserTime());
431 #else
432 return((double) clock()/CLK_TCK);
433 #endif
434 #endif
435 }
436