You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

570 lines
22 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% TTTTT IIIII M M EEEEE RRRR %
% T I MM MM E R R %
% T I M M M EEE RRRR %
% T I M M E R R %
% T IIIII M M EEEEE R R %
% %
% %
% MagickCore Timing Methods %
% %
% Software Design %
% Cristy %
% January 1993 %
% %
% %
% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Contributed by Bill Radcliffe and Bob Friesenhahn.
%
*/
/*
Include declarations.
*/
#include "MagickCore/studio.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/locale_.h"
#include "MagickCore/log.h"
#include "MagickCore/memory_.h"
#include "MagickCore/memory-private.h"
#include "MagickCore/nt-base-private.h"
#include "MagickCore/string-private.h"
#include "MagickCore/timer.h"
#include "MagickCore/timer-private.h"
/*
Define declarations.
*/
#if !defined(CLOCKS_PER_SEC)
#define CLOCKS_PER_SEC 100
#endif
/*
Forward declarations.
*/
static double
UserTime(void);
static void
StopTimer(TimerInfo *);
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% A c q u i r e T i m e r I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% AcquireTimerInfo() initializes the TimerInfo structure. It effectively
% creates a stopwatch and starts it.
%
% The format of the AcquireTimerInfo method is:
%
% TimerInfo *AcquireTimerInfo(void)
%
*/
MagickExport TimerInfo *AcquireTimerInfo(void)
{
TimerInfo
*timer_info;
timer_info=(TimerInfo *) AcquireCriticalMemory(sizeof(*timer_info));
(void) memset(timer_info,0,sizeof(*timer_info));
timer_info->signature=MagickCoreSignature;
GetTimerInfo(timer_info);
return(timer_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% C o n t i n u e T i m e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ContinueTimer() resumes a stopped stopwatch. The stopwatch continues
% counting from the last StartTimer() onwards.
%
% The format of the ContinueTimer method is:
%
% MagickBooleanType ContinueTimer(TimerInfo *time_info)
%
% A description of each parameter follows.
%
% o time_info: Time statistics structure.
%
*/
MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
{
assert(time_info != (TimerInfo *) NULL);
assert(time_info->signature == MagickCoreSignature);
if (time_info->state == UndefinedTimerState)
return(MagickFalse);
if (time_info->state == StoppedTimerState)
{
time_info->user.total-=time_info->user.stop-time_info->user.start;
time_info->elapsed.total-=time_info->elapsed.stop-
time_info->elapsed.start;
}
time_info->state=RunningTimerState;
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D e s t r o y T i m e r I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroyTimerInfo() zeros memory associated with the TimerInfo structure.
%
% The format of the DestroyTimerInfo method is:
%
% TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
%
% A description of each parameter follows:
%
% o timer_info: The cipher context.
%
*/
MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
{
assert(timer_info != (TimerInfo *) NULL);
assert(timer_info->signature == MagickCoreSignature);
timer_info->signature=(~MagickCoreSignature);
timer_info=(TimerInfo *) RelinquishMagickMemory(timer_info);
return(timer_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ E l a p s e d T i m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ElapsedTime() returns the elapsed time (in seconds) since the last call to
% StartTimer().
%
% The format of the ElapsedTime method is:
%
% double ElapsedTime()
%
*/
static double ElapsedTime(void)
{
#if defined(MAGICKCORE_HAVE_CLOCK_GETTIME)
#define NANOSECONDS_PER_SECOND 1000000000.0
#if defined(CLOCK_HIGHRES)
# define CLOCK_ID CLOCK_HIGHRES
#elif defined(CLOCK_MONOTONIC_RAW)
# define CLOCK_ID CLOCK_MONOTONIC_RAW
#elif defined(CLOCK_MONOTONIC_PRECISE)
# define CLOCK_ID CLOCK_MONOTONIC_PRECISE
#elif defined(CLOCK_MONOTONIC)
# define CLOCK_ID CLOCK_MONOTONIC
#else
# define CLOCK_ID CLOCK_REALTIME
#endif
struct timespec
timer;
(void) clock_gettime(CLOCK_ID,&timer);
return((double) timer.tv_sec+timer.tv_nsec/NANOSECONDS_PER_SECOND);
#elif defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
struct tms
timer;
return((double) times(&timer)/sysconf(_SC_CLK_TCK));
#else
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
return(NTElapsedTime());
#else
return((double) clock()/CLOCKS_PER_SEC);
#endif
#endif
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% F o r m a t M a g i c k T i m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FormatMagickTime() returns the specified time in the Internet date/time
% format and the length of the timestamp.
%
% The format of the FormatMagickTime method is:
%
% ssize_t FormatMagickTime(const time_t time,const size_t length,
% char *timestamp)
%
% A description of each parameter follows.
%
% o time: the time since the Epoch (00:00:00 UTC, January 1, 1970),
% measured in seconds.
%
% o length: the maximum length of the string.
%
% o timestamp: Return the Internet date/time here.
%
*/
MagickExport ssize_t FormatMagickTime(const time_t time,const size_t length,
char *timestamp)
{
ssize_t
count;
struct tm
utc_time;
assert(timestamp != (char *) NULL);
GetMagickUTCtime(&time,&utc_time);
count=FormatLocaleString(timestamp,length,
"%04d-%02d-%02dT%02d:%02d:%02d%+03d:00",utc_time.tm_year+1900,
utc_time.tm_mon+1,utc_time.tm_mday,utc_time.tm_hour,utc_time.tm_min,
utc_time.tm_sec,0);
return(count);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t E l a p s e d T i m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetElapsedTime() returns the elapsed time (in seconds) passed between the
% start and stop events. If the stopwatch is still running, it is stopped
% first.
%
% The format of the GetElapsedTime method is:
%
% double GetElapsedTime(TimerInfo *time_info)
%
% A description of each parameter follows.
%
% o time_info: Timer statistics structure.
%
*/
MagickExport double GetElapsedTime(TimerInfo *time_info)
{
assert(time_info != (TimerInfo *) NULL);
assert(time_info->signature == MagickCoreSignature);
if (time_info->state == UndefinedTimerState)
return(0.0);
if (time_info->state == RunningTimerState)
StopTimer(time_info);
return(time_info->elapsed.total);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t M a g i c k T i m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetMagickTime() returns the time as the number of seconds since the Epoch.
%
% The format of the GetElapsedTime method is:
%
% time_t GetElapsedTime(void)
%
*/
MagickExport time_t GetMagickTime(void)
{
static const char
*source_date_epoch = (const char *) NULL;
static MagickBooleanType
epoch_initalized = MagickFalse;
if (epoch_initalized == MagickFalse)
{
source_date_epoch=getenv("SOURCE_DATE_EPOCH");
epoch_initalized=MagickTrue;
}
if (source_date_epoch != (const char *) NULL)
{
time_t
epoch;
epoch=(time_t) StringToDouble(source_date_epoch,(char **) NULL);
if ((epoch > 0) && (epoch <= time((time_t *) NULL)))
return(epoch);
}
return(time((time_t *) NULL));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t T i m e r I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetTimerInfo() initializes the TimerInfo structure.
%
% The format of the GetTimerInfo method is:
%
% void GetTimerInfo(TimerInfo *time_info)
%
% A description of each parameter follows.
%
% o time_info: Timer statistics structure.
%
*/
MagickExport void GetTimerInfo(TimerInfo *time_info)
{
/*
Create a stopwatch and start it.
*/
assert(time_info != (TimerInfo *) NULL);
(void) memset(time_info,0,sizeof(*time_info));
time_info->state=UndefinedTimerState;
time_info->signature=MagickCoreSignature;
StartTimer(time_info,MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t U s e r T i m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetUserTime() returns the User time (user and system) by the operating
% system (in seconds) between the start and stop events. If the stopwatch is
% still running, it is stopped first.
%
% The format of the GetUserTime method is:
%
% double GetUserTime(TimerInfo *time_info)
%
% A description of each parameter follows.
%
% o time_info: Timer statistics structure.
%
*/
MagickExport double GetUserTime(TimerInfo *time_info)
{
assert(time_info != (TimerInfo *) NULL);
assert(time_info->signature == MagickCoreSignature);
if (time_info->state == UndefinedTimerState)
return(0.0);
if (time_info->state == RunningTimerState)
StopTimer(time_info);
return(time_info->user.total);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% R e s e t T i m e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ResetTimer() resets the stopwatch.
%
% The format of the ResetTimer method is:
%
% void ResetTimer(TimerInfo *time_info)
%
% A description of each parameter follows.
%
% o time_info: Timer statistics structure.
%
*/
MagickExport void ResetTimer(TimerInfo *time_info)
{
assert(time_info != (TimerInfo *) NULL);
assert(time_info->signature == MagickCoreSignature);
StopTimer(time_info);
time_info->elapsed.stop=0.0;
time_info->user.stop=0.0;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S t a r t T i m e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% StartTimer() starts the stopwatch.
%
% The format of the StartTimer method is:
%
% void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
%
% A description of each parameter follows.
%
% o time_info: Timer statistics structure.
%
% o reset: If reset is MagickTrue, then the stopwatch is reset prior to
% starting. If reset is MagickFalse, then timing is continued without
% resetting the stopwatch.
%
*/
MagickExport void StartTimer(TimerInfo *time_info,const MagickBooleanType reset)
{
assert(time_info != (TimerInfo *) NULL);
assert(time_info->signature == MagickCoreSignature);
if (reset != MagickFalse)
{
/*
Reset the stopwatch before starting it.
*/
time_info->user.total=0.0;
time_info->elapsed.total=0.0;
}
if (time_info->state != RunningTimerState)
{
time_info->elapsed.start=ElapsedTime();
time_info->user.start=UserTime();
}
time_info->state=RunningTimerState;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S t o p T i m e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% StopTimer() stops the stopwatch.
%
% The format of the StopTimer method is:
%
% void StopTimer(TimerInfo *time_info)
%
% A description of each parameter follows.
%
% o time_info: Timer statistics structure.
%
*/
static void StopTimer(TimerInfo *time_info)
{
assert(time_info != (TimerInfo *) NULL);
assert(time_info->signature == MagickCoreSignature);
time_info->elapsed.stop=ElapsedTime();
time_info->user.stop=UserTime();
if (time_info->state == RunningTimerState)
{
time_info->user.total+=time_info->user.stop-
time_info->user.start+MagickEpsilon;
time_info->elapsed.total+=time_info->elapsed.stop-
time_info->elapsed.start+MagickEpsilon;
}
time_info->state=StoppedTimerState;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ U s e r T i m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% UserTime() returns the total time the process has been scheduled (in
% seconds) since the last call to StartTimer().
%
% The format of the UserTime method is:
%
% double UserTime()
%
*/
static double UserTime(void)
{
#if defined(MAGICKCORE_HAVE_TIMES) && defined(MAGICKCORE_HAVE_SYSCONF)
struct tms
timer;
(void) times(&timer);
return((double) (timer.tms_utime+timer.tms_stime)/sysconf(_SC_CLK_TCK));
#else
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
return(NTUserTime());
#else
return((double) clock()/CLOCKS_PER_SEC);
#endif
#endif
}