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