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