2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % TTTTT IIIII M M EEEEE RRRR %
10 % T IIIII M M EEEEE R R %
13 % MagickCore Timing Methods %
20 % Copyright 1999-2018 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 % https://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/memory-private.h"
49 #include "MagickCore/nt-base-private.h"
50 #include "MagickCore/timer.h"
55 #if !defined(CLOCKS_PER_SEC)
56 #define CLOCKS_PER_SEC 100
66 StopTimer(TimerInfo *);
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 % A c q u i r e T i m e r I n f o %
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 % AcquireTimerInfo() initializes the TimerInfo structure. It effectively
80 % creates a stopwatch and starts it.
82 % The format of the AcquireTimerInfo method is:
84 % TimerInfo *AcquireTimerInfo(void)
87 MagickExport TimerInfo *AcquireTimerInfo(void)
92 timer_info=(TimerInfo *) AcquireCriticalMemory(sizeof(*timer_info));
93 (void) memset(timer_info,0,sizeof(*timer_info));
94 timer_info->signature=MagickCoreSignature;
95 GetTimerInfo(timer_info);
100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 % C o n t i n u e T i m e r %
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 % ContinueTimer() resumes a stopped stopwatch. The stopwatch continues
111 % counting from the last StartTimer() onwards.
113 % The format of the ContinueTimer method is:
115 % MagickBooleanType ContinueTimer(TimerInfo *time_info)
117 % A description of each parameter follows.
119 % o time_info: Time statistics structure.
122 MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
124 assert(time_info != (TimerInfo *) NULL);
125 assert(time_info->signature == MagickCoreSignature);
126 if (time_info->state == UndefinedTimerState)
128 if (time_info->state == StoppedTimerState)
130 time_info->user.total-=time_info->user.stop-time_info->user.start;
131 time_info->elapsed.total-=time_info->elapsed.stop-
132 time_info->elapsed.start;
134 time_info->state=RunningTimerState;
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 % D e s t r o y T i m e r I n f o %
147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 % DestroyTimerInfo() zeros memory associated with the TimerInfo structure.
151 % The format of the DestroyTimerInfo method is:
153 % TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
155 % A description of each parameter follows:
157 % o timer_info: The cipher context.
160 MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
162 assert(timer_info != (TimerInfo *) NULL);
163 assert(timer_info->signature == MagickCoreSignature);
164 timer_info->signature=(~MagickCoreSignature);
165 timer_info=(TimerInfo *) RelinquishMagickMemory(timer_info);
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 + E l a p s e d T i m e %
178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 % ElapsedTime() returns the elapsed time (in seconds) since the last call to
183 % The format of the ElapsedTime method is:
185 % double ElapsedTime()
188 static double ElapsedTime(void)
190 #if defined(HAVE_CLOCK_GETTIME)
191 #define NANOSECONDS_PER_SECOND 1000000000.0
192 #if defined(CLOCK_HIGHRES)
193 # define CLOCK_ID CLOCK_HIGHRES
194 #elif defined(CLOCK_MONOTONIC_RAW)
195 # define CLOCK_ID CLOCK_MONOTONIC_RAW
196 #elif defined(CLOCK_MONOTONIC_PRECISE)
197 # define CLOCK_ID CLOCK_MONOTONIC_PRECISE
198 #elif defined(CLOCK_MONOTONIC)
199 # define CLOCK_ID CLOCK_MONOTONIC
201 # define CLOCK_ID CLOCK_REALTIME
207 (void) clock_gettime(CLOCK_ID,&timer);
208 return((double) timer.tv_sec+timer.tv_nsec/NANOSECONDS_PER_SECOND);
209 #elif defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
213 return((double) times(&timer)/sysconf(_SC_CLK_TCK));
215 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
216 return(NTElapsedTime());
218 return((double) clock()/CLOCKS_PER_SEC);
224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228 % G e t E l a p s e d T i m e %
232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234 % GetElapsedTime() returns the elapsed time (in seconds) passed between the
235 % start and stop events. If the stopwatch is still running, it is stopped
238 % The format of the GetElapsedTime method is:
240 % double GetElapsedTime(TimerInfo *time_info)
242 % A description of each parameter follows.
244 % o time_info: Timer statistics structure.
247 MagickExport double GetElapsedTime(TimerInfo *time_info)
249 assert(time_info != (TimerInfo *) NULL);
250 assert(time_info->signature == MagickCoreSignature);
251 if (time_info->state == UndefinedTimerState)
253 if (time_info->state == RunningTimerState)
254 StopTimer(time_info);
255 return(time_info->elapsed.total);
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263 + G e t T i m e r I n f o %
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269 % GetTimerInfo() initializes the TimerInfo structure.
271 % The format of the GetTimerInfo method is:
273 % void GetTimerInfo(TimerInfo *time_info)
275 % A description of each parameter follows.
277 % o time_info: Timer statistics structure.
280 MagickExport void GetTimerInfo(TimerInfo *time_info)
283 Create a stopwatch and start it.
285 assert(time_info != (TimerInfo *) NULL);
286 (void) memset(time_info,0,sizeof(*time_info));
287 time_info->state=UndefinedTimerState;
288 time_info->signature=MagickCoreSignature;
289 StartTimer(time_info,MagickTrue);
293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 % G e t U s e r T i m e %
301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 % GetUserTime() returns the User time (user and system) by the operating
304 % system (in seconds) between the start and stop events. If the stopwatch is
305 % still running, it is stopped first.
307 % The format of the GetUserTime method is:
309 % double GetUserTime(TimerInfo *time_info)
311 % A description of each parameter follows.
313 % o time_info: Timer statistics structure.
316 MagickExport double GetUserTime(TimerInfo *time_info)
318 assert(time_info != (TimerInfo *) NULL);
319 assert(time_info->signature == MagickCoreSignature);
320 if (time_info->state == UndefinedTimerState)
322 if (time_info->state == RunningTimerState)
323 StopTimer(time_info);
324 return(time_info->user.total);
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332 % R e s e t T i m e r %
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
338 % ResetTimer() resets the stopwatch.
340 % The format of the ResetTimer method is:
342 % void ResetTimer(TimerInfo *time_info)
344 % A description of each parameter follows.
346 % o time_info: Timer statistics structure.
349 MagickExport void ResetTimer(TimerInfo *time_info)
351 assert(time_info != (TimerInfo *) NULL);
352 assert(time_info->signature == MagickCoreSignature);
353 StopTimer(time_info);
354 time_info->elapsed.stop=0.0;
355 time_info->user.stop=0.0;
359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363 + S t a r t T i m e r %
367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 % StartTimer() starts the stopwatch.
371 % The format of the StartTimer method is:
373 % void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
375 % A description of each parameter follows.
377 % o time_info: Timer statistics structure.
379 % o reset: If reset is MagickTrue, then the stopwatch is reset prior to
380 % starting. If reset is MagickFalse, then timing is continued without
381 % resetting the stopwatch.
384 MagickExport void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
386 assert(time_info != (TimerInfo *) NULL);
387 assert(time_info->signature == MagickCoreSignature);
388 if (reset != MagickFalse)
391 Reset the stopwatch before starting it.
393 time_info->user.total=0.0;
394 time_info->elapsed.total=0.0;
396 if (time_info->state != RunningTimerState)
398 time_info->elapsed.start=ElapsedTime();
399 time_info->user.start=UserTime();
401 time_info->state=RunningTimerState;
405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409 + S t o p T i m e r %
413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415 % StopTimer() stops the stopwatch.
417 % The format of the StopTimer method is:
419 % void StopTimer(TimerInfo *time_info)
421 % A description of each parameter follows.
423 % o time_info: Timer statistics structure.
426 static void StopTimer(TimerInfo *time_info)
428 assert(time_info != (TimerInfo *) NULL);
429 assert(time_info->signature == MagickCoreSignature);
430 time_info->elapsed.stop=ElapsedTime();
431 time_info->user.stop=UserTime();
432 if (time_info->state == RunningTimerState)
434 time_info->user.total+=time_info->user.stop-
435 time_info->user.start+MagickEpsilon;
436 time_info->elapsed.total+=time_info->elapsed.stop-
437 time_info->elapsed.start+MagickEpsilon;
439 time_info->state=StoppedTimerState;
443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453 % UserTime() returns the total time the process has been scheduled (in
454 % seconds) since the last call to StartTimer().
456 % The format of the UserTime method is:
461 static double UserTime(void)
463 #if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
467 (void) times(&timer);
468 return((double) (timer.tms_utime+timer.tms_stime)/sysconf(_SC_CLK_TCK));
470 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
471 return(NTUserTime());
473 return((double) clock()/CLOCKS_PER_SEC);