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