Home | History | Annotate | Download | only in MagickCore
      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