1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % TTTTT IIIII M M EEEEE RRRR %
7 % T I MM MM E R R %
8 % T I M M M EEE RRRR %
9 % T I M M E R R %
10 % T IIIII M M EEEEE R R %
11 % %
12 % %
13 % MagickCore Timing Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % January 1993 %
18 % %
19 % %
20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % http://www.imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 % Contributed by Bill Radcliffe and Bob Friesenhahn.
37 %
38 */
39
40 /*
41 Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/exception.h"
45 #include "MagickCore/exception-private.h"
46 #include "MagickCore/log.h"
47 #include "MagickCore/memory_.h"
48 #include "MagickCore/nt-base-private.h"
49 #include "MagickCore/timer.h"
50
51 /*
52 Define declarations.
53 */
54 #if !defined(CLOCKS_PER_SEC)
55 #define CLOCKS_PER_SEC 100
56 #endif
57
58 /*
59 Forward declarations.
60 */
61 static double
62 UserTime(void);
63
64 static void
65 StopTimer(TimerInfo *);
66
67 /*
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 % %
70 % %
71 % %
72 % A c q u i r e T i m e r I n f o %
73 % %
74 % %
75 % %
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 %
78 % AcquireTimerInfo() initializes the TimerInfo structure. It effectively
79 % creates a stopwatch and starts it.
80 %
81 % The format of the AcquireTimerInfo method is:
82 %
83 % TimerInfo *AcquireTimerInfo(void)
84 %
85 */
AcquireTimerInfo(void)86 MagickExport TimerInfo *AcquireTimerInfo(void)
87 {
88 TimerInfo
89 *timer_info;
90
91 timer_info=(TimerInfo *) AcquireMagickMemory(sizeof(*timer_info));
92 if (timer_info == (TimerInfo *) NULL)
93 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
94 (void) ResetMagickMemory(timer_info,0,sizeof(*timer_info));
95 timer_info->signature=MagickCoreSignature;
96 GetTimerInfo(timer_info);
97 return(timer_info);
98 }
99
100 /*
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 % %
103 % %
104 % %
105 % C o n t i n u e T i m e r %
106 % %
107 % %
108 % %
109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 %
111 % ContinueTimer() resumes a stopped stopwatch. The stopwatch continues
112 % counting from the last StartTimer() onwards.
113 %
114 % The format of the ContinueTimer method is:
115 %
116 % MagickBooleanType ContinueTimer(TimerInfo *time_info)
117 %
118 % A description of each parameter follows.
119 %
120 % o time_info: Time statistics structure.
121 %
122 */
ContinueTimer(TimerInfo * time_info)123 MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
124 {
125 assert(time_info != (TimerInfo *) NULL);
126 assert(time_info->signature == MagickCoreSignature);
127 if (time_info->state == UndefinedTimerState)
128 return(MagickFalse);
129 if (time_info->state == StoppedTimerState)
130 {
131 time_info->user.total-=time_info->user.stop-time_info->user.start;
132 time_info->elapsed.total-=time_info->elapsed.stop-
133 time_info->elapsed.start;
134 }
135 time_info->state=RunningTimerState;
136 return(MagickTrue);
137 }
138
139 /*
140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 % %
142 % %
143 % %
144 % D e s t r o y T i m e r I n f o %
145 % %
146 % %
147 % %
148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 %
150 % DestroyTimerInfo() zeros memory associated with the TimerInfo structure.
151 %
152 % The format of the DestroyTimerInfo method is:
153 %
154 % TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
155 %
156 % A description of each parameter follows:
157 %
158 % o timer_info: The cipher context.
159 %
160 */
DestroyTimerInfo(TimerInfo * timer_info)161 MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
162 {
163 assert(timer_info != (TimerInfo *) NULL);
164 assert(timer_info->signature == MagickCoreSignature);
165 timer_info->signature=(~MagickCoreSignature);
166 timer_info=(TimerInfo *) RelinquishMagickMemory(timer_info);
167 return(timer_info);
168 }
169
170 /*
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 % %
173 % %
174 % %
175 + E l a p s e d T i m e %
176 % %
177 % %
178 % %
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 %
181 % ElapsedTime() returns the elapsed time (in seconds) since the last call to
182 % StartTimer().
183 %
184 % The format of the ElapsedTime method is:
185 %
186 % double ElapsedTime()
187 %
188 */
ElapsedTime(void)189 static double ElapsedTime(void)
190 {
191 #if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
192 struct tms
193 timer;
194
195 return((double) times(&timer)/sysconf(_SC_CLK_TCK));
196 #else
197 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
198 return(NTElapsedTime());
199 #else
200 return((double) clock()/CLOCKS_PER_SEC);
201 #endif
202 #endif
203 }
204
205 /*
206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 % %
208 % %
209 % %
210 % G e t E l a p s e d T i m e %
211 % %
212 % %
213 % %
214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215 %
216 % GetElapsedTime() returns the elapsed time (in seconds) passed between the
217 % start and stop events. If the stopwatch is still running, it is stopped
218 % first.
219 %
220 % The format of the GetElapsedTime method is:
221 %
222 % double GetElapsedTime(TimerInfo *time_info)
223 %
224 % A description of each parameter follows.
225 %
226 % o time_info: Timer statistics structure.
227 %
228 */
GetElapsedTime(TimerInfo * time_info)229 MagickExport double GetElapsedTime(TimerInfo *time_info)
230 {
231 assert(time_info != (TimerInfo *) NULL);
232 assert(time_info->signature == MagickCoreSignature);
233 if (time_info->state == UndefinedTimerState)
234 return(0.0);
235 if (time_info->state == RunningTimerState)
236 StopTimer(time_info);
237 return(time_info->elapsed.total);
238 }
239
240 /*
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 % %
243 % %
244 % %
245 + G e t T i m e r I n f o %
246 % %
247 % %
248 % %
249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 %
251 % GetTimerInfo() initializes the TimerInfo structure.
252 %
253 % The format of the GetTimerInfo method is:
254 %
255 % void GetTimerInfo(TimerInfo *time_info)
256 %
257 % A description of each parameter follows.
258 %
259 % o time_info: Timer statistics structure.
260 %
261 */
GetTimerInfo(TimerInfo * time_info)262 MagickExport void GetTimerInfo(TimerInfo *time_info)
263 {
264 /*
265 Create a stopwatch and start it.
266 */
267 assert(time_info != (TimerInfo *) NULL);
268 (void) ResetMagickMemory(time_info,0,sizeof(*time_info));
269 time_info->state=UndefinedTimerState;
270 time_info->signature=MagickCoreSignature;
271 StartTimer(time_info,MagickTrue);
272 }
273
274 /*
275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276 % %
277 % %
278 % %
279 % G e t U s e r T i m e %
280 % %
281 % %
282 % %
283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284 %
285 % GetUserTime() returns the User time (user and system) by the operating
286 % system (in seconds) between the start and stop events. If the stopwatch is
287 % still running, it is stopped first.
288 %
289 % The format of the GetUserTime method is:
290 %
291 % double GetUserTime(TimerInfo *time_info)
292 %
293 % A description of each parameter follows.
294 %
295 % o time_info: Timer statistics structure.
296 %
297 */
GetUserTime(TimerInfo * time_info)298 MagickExport double GetUserTime(TimerInfo *time_info)
299 {
300 assert(time_info != (TimerInfo *) NULL);
301 assert(time_info->signature == MagickCoreSignature);
302 if (time_info->state == UndefinedTimerState)
303 return(0.0);
304 if (time_info->state == RunningTimerState)
305 StopTimer(time_info);
306 return(time_info->user.total);
307 }
308
309 /*
310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311 % %
312 % %
313 % %
314 % R e s e t T i m e r %
315 % %
316 % %
317 % %
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319 %
320 % ResetTimer() resets the stopwatch.
321 %
322 % The format of the ResetTimer method is:
323 %
324 % void ResetTimer(TimerInfo *time_info)
325 %
326 % A description of each parameter follows.
327 %
328 % o time_info: Timer statistics structure.
329 %
330 */
ResetTimer(TimerInfo * time_info)331 MagickExport void ResetTimer(TimerInfo *time_info)
332 {
333 assert(time_info != (TimerInfo *) NULL);
334 assert(time_info->signature == MagickCoreSignature);
335 StopTimer(time_info);
336 time_info->elapsed.stop=0.0;
337 time_info->user.stop=0.0;
338 }
339
340 /*
341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 % %
343 % %
344 % %
345 + S t a r t T i m e r %
346 % %
347 % %
348 % %
349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 %
351 % StartTimer() starts the stopwatch.
352 %
353 % The format of the StartTimer method is:
354 %
355 % void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
356 %
357 % A description of each parameter follows.
358 %
359 % o time_info: Timer statistics structure.
360 %
361 % o reset: If reset is MagickTrue, then the stopwatch is reset prior to
362 % starting. If reset is MagickFalse, then timing is continued without
363 % resetting the stopwatch.
364 %
365 */
StartTimer(TimerInfo * time_info,const MagickBooleanType reset)366 MagickExport void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
367 {
368 assert(time_info != (TimerInfo *) NULL);
369 assert(time_info->signature == MagickCoreSignature);
370 if (reset != MagickFalse)
371 {
372 /*
373 Reset the stopwatch before starting it.
374 */
375 time_info->user.total=0.0;
376 time_info->elapsed.total=0.0;
377 }
378 if (time_info->state != RunningTimerState)
379 {
380 time_info->elapsed.start=ElapsedTime();
381 time_info->user.start=UserTime();
382 }
383 time_info->state=RunningTimerState;
384 }
385
386 /*
387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
388 % %
389 % %
390 % %
391 + S t o p T i m e r %
392 % %
393 % %
394 % %
395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396 %
397 % StopTimer() stops the stopwatch.
398 %
399 % The format of the StopTimer method is:
400 %
401 % void StopTimer(TimerInfo *time_info)
402 %
403 % A description of each parameter follows.
404 %
405 % o time_info: Timer statistics structure.
406 %
407 */
StopTimer(TimerInfo * time_info)408 static void StopTimer(TimerInfo *time_info)
409 {
410 assert(time_info != (TimerInfo *) NULL);
411 assert(time_info->signature == MagickCoreSignature);
412 time_info->elapsed.stop=ElapsedTime();
413 time_info->user.stop=UserTime();
414 if (time_info->state == RunningTimerState)
415 {
416 time_info->user.total+=time_info->user.stop-
417 time_info->user.start+MagickEpsilon;
418 time_info->elapsed.total+=time_info->elapsed.stop-
419 time_info->elapsed.start+MagickEpsilon;
420 }
421 time_info->state=StoppedTimerState;
422 }
423
424 /*
425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426 % %
427 % %
428 % %
429 + U s e r T i m e %
430 % %
431 % %
432 % %
433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434 %
435 % UserTime() returns the total time the process has been scheduled (in
436 % seconds) since the last call to StartTimer().
437 %
438 % The format of the UserTime method is:
439 %
440 % double UserTime()
441 %
442 */
UserTime(void)443 static double UserTime(void)
444 {
445 #if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
446 struct tms
447 timer;
448
449 (void) times(&timer);
450 return((double) (timer.tms_utime+timer.tms_stime)/sysconf(_SC_CLK_TCK));
451 #else
452 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
453 return(NTUserTime());
454 #else
455 return((double) clock()/CLOCKS_PER_SEC);
456 #endif
457 #endif
458 }
459