MagickCore 6.9.12-98
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
timer.c
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 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% https://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/image-private.h"
47#include "magick/locale_.h"
48#include "magick/log.h"
49#include "magick/memory_.h"
50#include "magick/nt-base-private.h"
51#include "magick/resource_.h"
52#include "magick/string-private.h"
53#include "magick/timer.h"
54#include "magick/timer-private.h"
55
56/*
57 Define declarations.
58*/
59#if !defined(CLOCKS_PER_SEC)
60#define CLOCKS_PER_SEC 100
61#endif
62
63/*
64 Forward declarations.
65*/
66static double
67 UserTime(void);
68
69static void
70 StopTimer(TimerInfo *);
71
72/*
73%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74% %
75% %
76% %
77% A c q u i r e T i m e r I n f o %
78% %
79% %
80% %
81%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82%
83% AcquireTimerInfo() initializes the TimerInfo structure. It effectively
84% creates a stopwatch and starts it.
85%
86% The format of the AcquireTimerInfo method is:
87%
88% TimerInfo *AcquireTimerInfo(void)
89%
90*/
91MagickExport TimerInfo *AcquireTimerInfo(void)
92{
94 *timer_info;
95
96 timer_info=(TimerInfo *) AcquireMagickMemory(sizeof(*timer_info));
97 if (timer_info == (TimerInfo *) NULL)
98 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
99 (void) memset(timer_info,0,sizeof(*timer_info));
100 timer_info->signature=MagickCoreSignature;
101 GetTimerInfo(timer_info);
102 return(timer_info);
103}
104
105/*
106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107% %
108% %
109% %
110% C o n t i n u e T i m e r %
111% %
112% %
113% %
114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115%
116% ContinueTimer() resumes a stopped stopwatch. The stopwatch continues
117% counting from the last StartTimer() onwards.
118%
119% The format of the ContinueTimer method is:
120%
121% MagickBooleanType ContinueTimer(TimerInfo *time_info)
122%
123% A description of each parameter follows.
124%
125% o time_info: Time statistics structure.
126%
127*/
128MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
129{
130 assert(time_info != (TimerInfo *) NULL);
131 assert(time_info->signature == MagickCoreSignature);
132 if (time_info->state == UndefinedTimerState)
133 return(MagickFalse);
134 if (time_info->state == StoppedTimerState)
135 {
136 time_info->user.total-=time_info->user.stop-time_info->user.start;
137 time_info->elapsed.total-=time_info->elapsed.stop-
138 time_info->elapsed.start;
139 }
140 time_info->state=RunningTimerState;
141 return(MagickTrue);
142}
143
144/*
145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146% %
147% %
148% %
149% D e s t r o y T i m e r I n f o %
150% %
151% %
152% %
153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154%
155% DestroyTimerInfo() zeros memory associated with the TimerInfo structure.
156%
157% The format of the DestroyTimerInfo method is:
158%
159% TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
160%
161% A description of each parameter follows:
162%
163% o timer_info: The cipher context.
164%
165*/
166MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
167{
168 assert(timer_info != (TimerInfo *) NULL);
169 assert(timer_info->signature == MagickCoreSignature);
170 timer_info->signature=(~MagickCoreSignature);
171 timer_info=(TimerInfo *) RelinquishMagickMemory(timer_info);
172 return(timer_info);
173}
174
175/*
176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177% %
178% %
179% %
180+ E l a p s e d T i m e %
181% %
182% %
183% %
184%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
185%
186% ElapsedTime() returns the elapsed time (in seconds) since the last call to
187% StartTimer().
188%
189% The format of the ElapsedTime method is:
190%
191% double ElapsedTime()
192%
193*/
194static double ElapsedTime(void)
195{
196#if defined(MAGICKCORE_HAVE_CLOCK_GETTIME)
197#define NANOSECONDS_PER_SECOND 1000000000.0
198#if defined(CLOCK_HIGHRES)
199# define CLOCK_ID CLOCK_HIGHRES
200#elif defined(CLOCK_MONOTONIC_RAW)
201# define CLOCK_ID CLOCK_MONOTONIC_RAW
202#elif defined(CLOCK_MONOTONIC_PRECISE)
203# define CLOCK_ID CLOCK_MONOTONIC_PRECISE
204#elif defined(CLOCK_MONOTONIC)
205# define CLOCK_ID CLOCK_MONOTONIC
206#else
207# define CLOCK_ID CLOCK_REALTIME
208#endif
209
210 struct timespec
211 timer;
212
213 (void) clock_gettime(CLOCK_ID,&timer);
214 return((double) timer.tv_sec+timer.tv_nsec/NANOSECONDS_PER_SECOND);
215#elif defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
216 struct tms
217 timer;
218
219 return((double) times(&timer)/sysconf(_SC_CLK_TCK));
220#else
221#if defined(MAGICKCORE_WINDOWS_SUPPORT)
222 return(NTElapsedTime());
223#else
224 return((double) clock()/CLOCKS_PER_SEC);
225#endif
226#endif
227}
228
229/*
230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231% %
232% %
233% %
234% F o r m a t M a g i c k T i m e %
235% %
236% %
237% %
238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239%
240% FormatMagickTime() returns the specified time in the Internet date/time
241% format and the length of the timestamp.
242%
243% The format of the FormatMagickTime method is:
244%
245% ssize_t FormatMagickTime(const time_t time,const size_t length,
246% char *timestamp)
247%
248% A description of each parameter follows.
249%
250% o time: the time since the Epoch (00:00:00 UTC, January 1, 1970),
251% measured in seconds.
252%
253% o length: the maximum length of the string.
254%
255% o timestamp: Return the Internet date/time here.
256%
257*/
258MagickExport ssize_t FormatMagickTime(const time_t time,const size_t length,
259 char *timestamp)
260{
261 ssize_t
262 count;
263
264 struct tm
265 utc_time;
266
267 assert(timestamp != (char *) NULL);
268 GetMagickUTCtime(&time,&utc_time);
269 count=FormatLocaleString(timestamp,length,
270 "%04d-%02d-%02dT%02d:%02d:%02d%+03d:00",utc_time.tm_year+1900,
271 utc_time.tm_mon+1,utc_time.tm_mday,utc_time.tm_hour,utc_time.tm_min,
272 utc_time.tm_sec,0);
273 return(count);
274}
275
276/*
277%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278% %
279% %
280% %
281% G e t E l a p s e d T i m e %
282% %
283% %
284% %
285%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286%
287% GetElapsedTime() returns the elapsed time (in seconds) passed between the
288% start and stop events. If the stopwatch is still running, it is stopped
289% first.
290%
291% The format of the GetElapsedTime method is:
292%
293% double GetElapsedTime(TimerInfo *time_info)
294%
295% A description of each parameter follows.
296%
297% o time_info: Timer statistics structure.
298%
299*/
300MagickExport double GetElapsedTime(TimerInfo *time_info)
301{
302 assert(time_info != (TimerInfo *) NULL);
303 assert(time_info->signature == MagickCoreSignature);
304 if (time_info->state == UndefinedTimerState)
305 return(0.0);
306 if (time_info->state == RunningTimerState)
307 StopTimer(time_info);
308 return(time_info->elapsed.total);
309}
310
311/*
312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313% %
314% %
315% %
316+ G e t M a g i c k T i m e %
317% %
318% %
319% %
320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321%
322% GetMagickTime() returns the time as the number of seconds since the Epoch.
323%
324% The format of the GetMagickTime method is:
325%
326% time_t GetMagickTime(void)
327%
328*/
329MagickExport time_t GetMagickTime(void)
330{
331 static time_t
332 constant_magick_time = (time_t) 0;
333
334 static MagickBooleanType
335 epoch_initialized = MagickFalse;
336
337 if (epoch_initialized == MagickFalse)
338 {
339 const char
340 *source_date_epoch;
341
342 epoch_initialized=MagickTrue;
343 source_date_epoch=getenv("SOURCE_DATE_EPOCH");
344 if (source_date_epoch != (const char *) NULL)
345 {
346 time_t
347 epoch;
348
349 epoch=(time_t) CastDoubleToLong(StringToDouble(source_date_epoch,
350 (char **) NULL));
351 if ((epoch > 0) && (epoch <= time((time_t *) NULL)))
352 constant_magick_time=epoch;
353 }
354 }
355 if (constant_magick_time != 0)
356 return(constant_magick_time);
357 return(time((time_t *) NULL));
358}
359
360/*
361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362% %
363% %
364% %
365+ G e t M a g i c k T T L %
366% %
367% %
368% %
369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370%
371% GetMagickTTL() returns the time as the number of seconds to live.
372%
373% The format of the GetMagickTTL method is:
374%
375% MagickSizeType GetMagickTTL(void)
376%
377*/
378MagickPrivate MagickOffsetType GetMagickTTL(void)
379{
380 static time_t
381 magick_epoch = (time_t) 0;
382
383 static MagickBooleanType
384 epoch_initialized = MagickFalse;
385
386 if (epoch_initialized == MagickFalse)
387 {
388 epoch_initialized=MagickTrue;
389 magick_epoch=time((time_t *) NULL);
390 }
391 return((MagickOffsetType) GetMagickResourceLimit(TimeResource)-
392 (time((time_t *) NULL)-magick_epoch));
393}
394
395/*
396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397% %
398% %
399% %
400+ G e t T i m e r I n f o %
401% %
402% %
403% %
404%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405%
406% GetTimerInfo() initializes the TimerInfo structure.
407%
408% The format of the GetTimerInfo method is:
409%
410% void GetTimerInfo(TimerInfo *time_info)
411%
412% A description of each parameter follows.
413%
414% o time_info: Timer statistics structure.
415%
416*/
417MagickExport void GetTimerInfo(TimerInfo *time_info)
418{
419 /*
420 Create a stopwatch and start it.
421 */
422 assert(time_info != (TimerInfo *) NULL);
423 (void) memset(time_info,0,sizeof(*time_info));
424 time_info->state=UndefinedTimerState;
425 time_info->signature=MagickCoreSignature;
426 StartTimer(time_info,MagickTrue);
427}
428
429/*
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431% %
432% %
433% %
434% G e t U s e r T i m e %
435% %
436% %
437% %
438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439%
440% GetUserTime() returns the User time (user and system) by the operating
441% system (in seconds) between the start and stop events. If the stopwatch is
442% still running, it is stopped first.
443%
444% The format of the GetUserTime method is:
445%
446% double GetUserTime(TimerInfo *time_info)
447%
448% A description of each parameter follows.
449%
450% o time_info: Timer statistics structure.
451%
452*/
453MagickExport double GetUserTime(TimerInfo *time_info)
454{
455 assert(time_info != (TimerInfo *) NULL);
456 assert(time_info->signature == MagickCoreSignature);
457 if (time_info->state == UndefinedTimerState)
458 return(0.0);
459 if (time_info->state == RunningTimerState)
460 StopTimer(time_info);
461 return(time_info->user.total);
462}
463
464/*
465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
466% %
467% %
468% %
469% R e s e t T i m e r %
470% %
471% %
472% %
473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
474%
475% ResetTimer() resets the stopwatch.
476%
477% The format of the ResetTimer method is:
478%
479% void ResetTimer(TimerInfo *time_info)
480%
481% A description of each parameter follows.
482%
483% o time_info: Timer statistics structure.
484%
485*/
486MagickExport void ResetTimer(TimerInfo *time_info)
487{
488 assert(time_info != (TimerInfo *) NULL);
489 assert(time_info->signature == MagickCoreSignature);
490 StopTimer(time_info);
491 time_info->elapsed.stop=0.0;
492 time_info->user.stop=0.0;
493}
494
495/*
496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
497% %
498% %
499% %
500+ S t a r t T i m e r %
501% %
502% %
503% %
504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505%
506% StartTimer() starts the stopwatch.
507%
508% The format of the StartTimer method is:
509%
510% void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
511%
512% A description of each parameter follows.
513%
514% o time_info: Timer statistics structure.
515%
516% o reset: If reset is MagickTrue, then the stopwatch is reset prior to
517% starting. If reset is MagickFalse, then timing is continued without
518% resetting the stopwatch.
519%
520*/
521MagickExport void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
522{
523 assert(time_info != (TimerInfo *) NULL);
524 assert(time_info->signature == MagickCoreSignature);
525 if (reset != MagickFalse)
526 {
527 /*
528 Reset the stopwatch before starting it.
529 */
530 time_info->user.total=0.0;
531 time_info->elapsed.total=0.0;
532 }
533 if (time_info->state != RunningTimerState)
534 {
535 time_info->elapsed.start=ElapsedTime();
536 time_info->user.start=UserTime();
537 }
538 time_info->state=RunningTimerState;
539}
540
541/*
542%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
543% %
544% %
545% %
546+ S t o p T i m e r %
547% %
548% %
549% %
550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551%
552% StopTimer() stops the stopwatch.
553%
554% The format of the StopTimer method is:
555%
556% void StopTimer(TimerInfo *time_info)
557%
558% A description of each parameter follows.
559%
560% o time_info: Timer statistics structure.
561%
562*/
563static void StopTimer(TimerInfo *time_info)
564{
565 assert(time_info != (TimerInfo *) NULL);
566 assert(time_info->signature == MagickCoreSignature);
567 time_info->elapsed.stop=ElapsedTime();
568 time_info->user.stop=UserTime();
569 if (time_info->state == RunningTimerState)
570 {
571 time_info->user.total+=time_info->user.stop-
572 time_info->user.start+MagickEpsilon;
573 time_info->elapsed.total+=time_info->elapsed.stop-
574 time_info->elapsed.start+MagickEpsilon;
575 }
576 time_info->state=StoppedTimerState;
577}
578
579/*
580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
581% %
582% %
583% %
584+ U s e r T i m e %
585% %
586% %
587% %
588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589%
590% UserTime() returns the total time the process has been scheduled (in
591% seconds) since the last call to StartTimer().
592%
593% The format of the UserTime method is:
594%
595% double UserTime()
596%
597*/
598static double UserTime(void)
599{
600#if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
601 struct tms
602 timer;
603
604 (void) times(&timer);
605 return((double) (timer.tms_utime+timer.tms_stime)/sysconf(_SC_CLK_TCK));
606#else
607#if defined(MAGICKCORE_WINDOWS_SUPPORT)
608 return(NTUserTime());
609#else
610 return((double) clock()/CLOCKS_PER_SEC);
611#endif
612#endif
613}