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