2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % TTTTT IIIII M M EEEEE RRRR %
10 % T IIIII M M EEEEE R R %
13 % MagickCore Timing Methods %
20 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 % Contributed by Bill Radcliffe and Bob Friesenhahn.
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/timer.h"
53 #if defined(macintosh)
54 #define CLK_TCK CLOCKS_PER_SEC
57 #define CLK_TCK sysconf(_SC_CLK_TCK)
67 StopTimer(TimerInfo *);
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74 % A c q u i r e T i m e r I n f o %
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 % AcquireTimerInfo() initializes the TimerInfo structure. It effectively
81 % creates a stopwatch and starts it.
83 % The format of the AcquireTimerInfo method is:
85 % TimerInfo *AcquireTimerInfo(void)
88 MagickExport TimerInfo *AcquireTimerInfo(void)
93 timer_info=(TimerInfo *) AcquireMagickMemory(sizeof(*timer_info));
94 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);
103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107 % C o n t i n u e T i m e r %
111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113 % ContinueTimer() resumes a stopped stopwatch. The stopwatch continues
114 % counting from the last StartTimer() onwards.
116 % The format of the ContinueTimer method is:
118 % MagickBooleanType ContinueTimer(TimerInfo *time_info)
120 % A description of each parameter follows.
122 % o time_info: Time statistics structure.
125 MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
127 assert(time_info != (TimerInfo *) NULL);
128 assert(time_info->signature == MagickSignature);
129 if (time_info->state == UndefinedTimerState)
131 if (time_info->state == StoppedTimerState)
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;
137 time_info->state=RunningTimerState;
142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146 % D e s t r o y T i m e r I n f o %
150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152 % DestroyTimerInfo() zeros memory associated with the TimerInfo structure.
154 % The format of the DestroyTimerInfo method is:
156 % TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
158 % A description of each parameter follows:
160 % o timer_info: The cipher context.
163 MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
165 assert(timer_info != (TimerInfo *) NULL);
166 assert(timer_info->signature == MagickSignature);
167 timer_info->signature=(~MagickSignature);
168 timer_info=(TimerInfo *) RelinquishMagickMemory(timer_info);
173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177 + E l a p s e d T i m e %
181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183 % ElapsedTime() returns the elapsed time (in seconds) since the last call to
186 % The format of the ElapsedTime method is:
188 % double ElapsedTime()
191 static double ElapsedTime(void)
193 #if defined(MAGICKCORE_HAVE_TIMES)
197 return((double) times(&timer)/CLK_TCK);
199 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
200 return(NTElapsedTime());
202 return((double) clock()/CLK_TCK);
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212 % G e t E l a p s e d T i m e %
216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
222 % The format of the GetElapsedTime method is:
224 % double GetElapsedTime(TimerInfo *time_info)
226 % A description of each parameter follows.
228 % o time_info: Timer statistics structure.
231 MagickExport double GetElapsedTime(TimerInfo *time_info)
233 assert(time_info != (TimerInfo *) NULL);
234 assert(time_info->signature == MagickSignature);
235 if (time_info->state == UndefinedTimerState)
237 if (time_info->state == RunningTimerState)
238 StopTimer(time_info);
239 return(time_info->elapsed.total);
243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 + G e t T i m e r I n f o %
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 % GetTimerInfo() initializes the TimerInfo structure.
255 % The format of the GetTimerInfo method is:
257 % void GetTimerInfo(TimerInfo *time_info)
259 % A description of each parameter follows.
261 % o time_info: Timer statistics structure.
264 MagickExport void GetTimerInfo(TimerInfo *time_info)
267 Create a stopwatch and start it.
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);
277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
281 % G e t U s e r T i m e %
285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
291 % The format of the GetUserTime method is:
293 % double GetUserTime(TimerInfo *time_info)
295 % A description of each parameter follows.
297 % o time_info: Timer statistics structure.
300 MagickExport double GetUserTime(TimerInfo *time_info)
302 assert(time_info != (TimerInfo *) NULL);
303 assert(time_info->signature == MagickSignature);
304 if (time_info->state == UndefinedTimerState)
306 if (time_info->state == RunningTimerState)
307 StopTimer(time_info);
308 return(time_info->user.total);
312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316 % R e s e t T i m e r %
320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322 % ResetTimer() resets the stopwatch.
324 % The format of the ResetTimer method is:
326 % void ResetTimer(TimerInfo *time_info)
328 % A description of each parameter follows.
330 % o time_info: Timer statistics structure.
333 MagickExport void ResetTimer(TimerInfo *time_info)
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;
343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347 + S t a r t T i m e r %
351 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353 % StartTimer() starts the stopwatch.
355 % The format of the StartTimer method is:
357 % void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
359 % A description of each parameter follows.
361 % o time_info: Timer statistics structure.
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.
368 MagickExport void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
370 assert(time_info != (TimerInfo *) NULL);
371 assert(time_info->signature == MagickSignature);
372 if (reset != MagickFalse)
375 Reset the stopwatch before starting it.
377 time_info->user.total=0.0;
378 time_info->elapsed.total=0.0;
380 if (time_info->state != RunningTimerState)
382 time_info->elapsed.start=ElapsedTime();
383 time_info->user.start=UserTime();
385 time_info->state=RunningTimerState;
389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393 + S t o p T i m e r %
397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 % StopTimer() stops the stopwatch.
401 % The format of the StopTimer method is:
403 % void StopTimer(TimerInfo *time_info)
405 % A description of each parameter follows.
407 % o time_info: Timer statistics structure.
410 static void StopTimer(TimerInfo *time_info)
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)
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;
423 time_info->state=StoppedTimerState;
427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437 % UserTime() returns the total time the process has been scheduled (in
438 % seconds) since the last call to StartTimer().
440 % The format of the UserTime method is:
445 static double UserTime(void)
447 #if defined(MAGICKCORE_HAVE_TIMES)
451 (void) times(&timer);
452 return((double) (timer.tms_utime+timer.tms_stime)/CLK_TCK);
454 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
455 return(NTUserTime());
457 return((double) clock()/CLK_TCK);