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