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-2016 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% http://www.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/log.h" 47#include "MagickCore/memory_.h" 48#include "MagickCore/nt-base-private.h" 49#include "MagickCore/timer.h" 50 51/* 52 Define declarations. 53*/ 54#if !defined(CLOCKS_PER_SEC) 55#define CLOCKS_PER_SEC 100 56#endif 57 58/* 59 Forward declarations. 60*/ 61static double 62 UserTime(void); 63 64static void 65 StopTimer(TimerInfo *); 66 67/* 68%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 69% % 70% % 71% % 72% A c q u i r e T i m e r I n f o % 73% % 74% % 75% % 76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 77% 78% AcquireTimerInfo() initializes the TimerInfo structure. It effectively 79% creates a stopwatch and starts it. 80% 81% The format of the AcquireTimerInfo method is: 82% 83% TimerInfo *AcquireTimerInfo(void) 84% 85*/ 86MagickExport TimerInfo *AcquireTimerInfo(void) 87{ 88 TimerInfo 89 *timer_info; 90 91 timer_info=(TimerInfo *) AcquireMagickMemory(sizeof(*timer_info)); 92 if (timer_info == (TimerInfo *) NULL) 93 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString"); 94 (void) ResetMagickMemory(timer_info,0,sizeof(*timer_info)); 95 timer_info->signature=MagickCoreSignature; 96 GetTimerInfo(timer_info); 97 return(timer_info); 98} 99 100/* 101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 102% % 103% % 104% % 105% C o n t i n u e T i m e r % 106% % 107% % 108% % 109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 110% 111% ContinueTimer() resumes a stopped stopwatch. The stopwatch continues 112% counting from the last StartTimer() onwards. 113% 114% The format of the ContinueTimer method is: 115% 116% MagickBooleanType ContinueTimer(TimerInfo *time_info) 117% 118% A description of each parameter follows. 119% 120% o time_info: Time statistics structure. 121% 122*/ 123MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info) 124{ 125 assert(time_info != (TimerInfo *) NULL); 126 assert(time_info->signature == MagickCoreSignature); 127 if (time_info->state == UndefinedTimerState) 128 return(MagickFalse); 129 if (time_info->state == StoppedTimerState) 130 { 131 time_info->user.total-=time_info->user.stop-time_info->user.start; 132 time_info->elapsed.total-=time_info->elapsed.stop- 133 time_info->elapsed.start; 134 } 135 time_info->state=RunningTimerState; 136 return(MagickTrue); 137} 138 139/* 140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 141% % 142% % 143% % 144% D e s t r o y T i m e r I n f o % 145% % 146% % 147% % 148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 149% 150% DestroyTimerInfo() zeros memory associated with the TimerInfo structure. 151% 152% The format of the DestroyTimerInfo method is: 153% 154% TimerInfo *DestroyTimerInfo(TimerInfo *timer_info) 155% 156% A description of each parameter follows: 157% 158% o timer_info: The cipher context. 159% 160*/ 161MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info) 162{ 163 assert(timer_info != (TimerInfo *) NULL); 164 assert(timer_info->signature == MagickCoreSignature); 165 timer_info->signature=(~MagickCoreSignature); 166 timer_info=(TimerInfo *) RelinquishMagickMemory(timer_info); 167 return(timer_info); 168} 169 170/* 171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 172% % 173% % 174% % 175+ E l a p s e d T i m e % 176% % 177% % 178% % 179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 180% 181% ElapsedTime() returns the elapsed time (in seconds) since the last call to 182% StartTimer(). 183% 184% The format of the ElapsedTime method is: 185% 186% double ElapsedTime() 187% 188*/ 189static double ElapsedTime(void) 190{ 191#if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF) 192 struct tms 193 timer; 194 195 return((double) times(&timer)/sysconf(_SC_CLK_TCK)); 196#else 197#if defined(MAGICKCORE_WINDOWS_SUPPORT) 198 return(NTElapsedTime()); 199#else 200 return((double) clock()/CLOCKS_PER_SEC); 201#endif 202#endif 203} 204 205/* 206%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 207% % 208% % 209% % 210% G e t E l a p s e d T i m e % 211% % 212% % 213% % 214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 215% 216% GetElapsedTime() returns the elapsed time (in seconds) passed between the 217% start and stop events. If the stopwatch is still running, it is stopped 218% first. 219% 220% The format of the GetElapsedTime method is: 221% 222% double GetElapsedTime(TimerInfo *time_info) 223% 224% A description of each parameter follows. 225% 226% o time_info: Timer statistics structure. 227% 228*/ 229MagickExport double GetElapsedTime(TimerInfo *time_info) 230{ 231 assert(time_info != (TimerInfo *) NULL); 232 assert(time_info->signature == MagickCoreSignature); 233 if (time_info->state == UndefinedTimerState) 234 return(0.0); 235 if (time_info->state == RunningTimerState) 236 StopTimer(time_info); 237 return(time_info->elapsed.total); 238} 239 240/* 241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 242% % 243% % 244% % 245+ G e t T i m e r I n f o % 246% % 247% % 248% % 249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 250% 251% GetTimerInfo() initializes the TimerInfo structure. 252% 253% The format of the GetTimerInfo method is: 254% 255% void GetTimerInfo(TimerInfo *time_info) 256% 257% A description of each parameter follows. 258% 259% o time_info: Timer statistics structure. 260% 261*/ 262MagickExport void GetTimerInfo(TimerInfo *time_info) 263{ 264 /* 265 Create a stopwatch and start it. 266 */ 267 assert(time_info != (TimerInfo *) NULL); 268 (void) ResetMagickMemory(time_info,0,sizeof(*time_info)); 269 time_info->state=UndefinedTimerState; 270 time_info->signature=MagickCoreSignature; 271 StartTimer(time_info,MagickTrue); 272} 273 274/* 275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 276% % 277% % 278% % 279% G e t U s e r T i m e % 280% % 281% % 282% % 283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 284% 285% GetUserTime() returns the User time (user and system) by the operating 286% system (in seconds) between the start and stop events. If the stopwatch is 287% still running, it is stopped first. 288% 289% The format of the GetUserTime method is: 290% 291% double GetUserTime(TimerInfo *time_info) 292% 293% A description of each parameter follows. 294% 295% o time_info: Timer statistics structure. 296% 297*/ 298MagickExport double GetUserTime(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->user.total); 307} 308 309/* 310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 311% % 312% % 313% % 314% R e s e t T i m e r % 315% % 316% % 317% % 318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 319% 320% ResetTimer() resets the stopwatch. 321% 322% The format of the ResetTimer method is: 323% 324% void ResetTimer(TimerInfo *time_info) 325% 326% A description of each parameter follows. 327% 328% o time_info: Timer statistics structure. 329% 330*/ 331MagickExport void ResetTimer(TimerInfo *time_info) 332{ 333 assert(time_info != (TimerInfo *) NULL); 334 assert(time_info->signature == MagickCoreSignature); 335 StopTimer(time_info); 336 time_info->elapsed.stop=0.0; 337 time_info->user.stop=0.0; 338} 339 340/* 341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 342% % 343% % 344% % 345+ S t a r t T i m e r % 346% % 347% % 348% % 349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 350% 351% StartTimer() starts the stopwatch. 352% 353% The format of the StartTimer method is: 354% 355% void StartTimer(TimerInfo *time_info,const MagickBooleanType reset) 356% 357% A description of each parameter follows. 358% 359% o time_info: Timer statistics structure. 360% 361% o reset: If reset is MagickTrue, then the stopwatch is reset prior to 362% starting. If reset is MagickFalse, then timing is continued without 363% resetting the stopwatch. 364% 365*/ 366MagickExport void StartTimer(TimerInfo *time_info,const MagickBooleanType reset) 367{ 368 assert(time_info != (TimerInfo *) NULL); 369 assert(time_info->signature == MagickCoreSignature); 370 if (reset != MagickFalse) 371 { 372 /* 373 Reset the stopwatch before starting it. 374 */ 375 time_info->user.total=0.0; 376 time_info->elapsed.total=0.0; 377 } 378 if (time_info->state != RunningTimerState) 379 { 380 time_info->elapsed.start=ElapsedTime(); 381 time_info->user.start=UserTime(); 382 } 383 time_info->state=RunningTimerState; 384} 385 386/* 387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 388% % 389% % 390% % 391+ S t o p T i m e r % 392% % 393% % 394% % 395%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 396% 397% StopTimer() stops the stopwatch. 398% 399% The format of the StopTimer method is: 400% 401% void StopTimer(TimerInfo *time_info) 402% 403% A description of each parameter follows. 404% 405% o time_info: Timer statistics structure. 406% 407*/ 408static void StopTimer(TimerInfo *time_info) 409{ 410 assert(time_info != (TimerInfo *) NULL); 411 assert(time_info->signature == MagickCoreSignature); 412 time_info->elapsed.stop=ElapsedTime(); 413 time_info->user.stop=UserTime(); 414 if (time_info->state == RunningTimerState) 415 { 416 time_info->user.total+=time_info->user.stop- 417 time_info->user.start+MagickEpsilon; 418 time_info->elapsed.total+=time_info->elapsed.stop- 419 time_info->elapsed.start+MagickEpsilon; 420 } 421 time_info->state=StoppedTimerState; 422} 423 424/* 425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 426% % 427% % 428% % 429+ U s e r T i m e % 430% % 431% % 432% % 433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 434% 435% UserTime() returns the total time the process has been scheduled (in 436% seconds) since the last call to StartTimer(). 437% 438% The format of the UserTime method is: 439% 440% double UserTime() 441% 442*/ 443static double UserTime(void) 444{ 445#if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF) 446 struct tms 447 timer; 448 449 (void) times(&timer); 450 return((double) (timer.tms_utime+timer.tms_stime)/sysconf(_SC_CLK_TCK)); 451#else 452#if defined(MAGICKCORE_WINDOWS_SUPPORT) 453 return(NTUserTime()); 454#else 455 return((double) clock()/CLOCKS_PER_SEC); 456#endif 457#endif 458} 459