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