Unit CastleTimeUtils

Description

Time utilities.

Note that the initialization of this unit calls CastleRandomize (which on most platforms just calls standard Randomize) to initialize random sequence of the standard Random.

Uses

  • BaseUnix
  • Unix
  • Dl
  • SysUtils
  • Math
  • Generics.Collections
  • CastleUtils

Overview

Classes, Interfaces, Objects and Records

Name Description
Record TTimerResult Current time from Timer.
Record TProcessTimerResult Current time from ProcessTimer.
Class TFramesPerSecond Utility to measure frames per second, independent of actual rendering API.
Record TCastleProfilerTime Structure obtained by calling TCastleProfiler.Start.
Class TCastleProfiler Profiler, to measure the speed of execution of your code.
Class TCastleFrameProfiler Profiler gathering statistics about each game frame.

Functions and Procedures

function CastleGetTickCount64: QWord;
function TimeTickSecondLater(const FirstTime, SecondTime, TimeDelay: TMilisecTime): boolean; deprecated 'to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds';
function TimeTickDiff(const FirstTime, SecondTime: TMilisecTime): TMilisecTime; deprecated 'to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds. Also, this function has non-intuitive argument order, inconsistent with ProcessTimerSeconds and TimerSeconds';
function MilisecTimesAdd(const t1, t2: TMilisecTime): TMilisecTime; deprecated 'to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds';
function MilisecTimesSubtract(const t1, t2: TMilisecTime): TMilisecTime; deprecated 'to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds';
function DateTimeToAtStr(const DateTime: TDateTime): string;
function Timer: TTimerResult;
function TimerSeconds(const A, B: TTimerResult): TFloatTime;
function ProcessTimer: TProcessTimerResult;
function ProcessTimerNow: TProcessTimerResult; deprecated 'use ProcessTimer';
function ProcessTimerSeconds(const a, b: TProcessTimerResult): TFloatTime;
procedure ProcessTimerBegin; deprecated 'instead of this, better to use a local variable, and ProcessTimer and ProcessTimerSeconds';
function ProcessTimerEnd: TFloatTime; deprecated 'instead of this, better to use a local variable, and ProcessTimer and ProcessTimerSeconds';
function Profiler: TCastleProfiler;
function FrameProfiler: TCastleFrameProfiler;
function CastleNow: TDateTime;
function CastleToday: TDateTime;
function CastleYesterday: TDateTime;
function CastleTomorrow: TDateTime;
procedure CastleRandomize;

Types

TFloatTime = Double;
TMilisecTime = QWord deprecated 'To measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds' ;
TFrameId = QWord;
TFrameMetric = (...);

Constants

OldestTime = -MaxDouble;
MinDateTime: TDateTime = MinDouble;

Description

Functions and Procedures

function CastleGetTickCount64: QWord;

Just like standard GetTickCount64 function, but works on all platforms supported by CGE. On Nintendo Switch the standard function will crash now.

function TimeTickSecondLater(const FirstTime, SecondTime, TimeDelay: TMilisecTime): boolean; deprecated 'to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds';

Warning: this symbol is deprecated: to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds

Check is SecondTime larger by at least TimeDelay than FirstTime.

Simple implementation of this would be SecondTime - FirstTime >= TimeDelay.

FirstTime and SecondTime are milisecond times from some initial point. For example, they may be taken from a function like 32-bit GetTickCount (but you actually should use GetTickCount64 with new compilers, never 32-bit GetTickCount). Such time may "wrap". This function checks these times intelligently, using the assumption that the SecondTime is always "later" than the FirstTime, and only having to check if it's later by at least TimeDelay.

Always TimeTickSecond(X, X, 0) = True. that is, when both times are actually equal, it's correctly "later by zero miliseconds".

function TimeTickDiff(const FirstTime, SecondTime: TMilisecTime): TMilisecTime; deprecated 'to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds. Also, this function has non-intuitive argument order, inconsistent with ProcessTimerSeconds and TimerSeconds';

Warning: this symbol is deprecated: to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds. Also, this function has non-intuitive argument order, inconsistent with ProcessTimerSeconds and TimerSeconds

Difference in times between SecondTime and FirstTime.

Naive implementation would be just SecondTime - FirstTime, this function does a little better: takes into account that times may "wrap" (see TimeTickSecondLater), and uses the assumption that the SecondTime for sure "later", to calculate hopefully correct difference.

function MilisecTimesAdd(const t1, t2: TMilisecTime): TMilisecTime; deprecated 'to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds';

Warning: this symbol is deprecated: to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds

Simply add and subtract two TMilisecTime values.

These don't care if TMilisecTime is a point in time, or time interval. They simply add / subtract values. It's your problem if adding / subtracting them is sensible.

Range checking is ignored. In particular, this means that if you subtract smaller value from larger value, the result will be like the time "wrapped" in between (since TMilisecTime range is limited).

function MilisecTimesSubtract(const t1, t2: TMilisecTime): TMilisecTime; deprecated 'to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds';

Warning: this symbol is deprecated: to measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds

 
function DateTimeToAtStr(const DateTime: TDateTime): string;

Convert DateTime to string in the form "date at time".

function Timer: TTimerResult;

Timer to measure (real) time passed during some operations. It is a "real" time, which means that subtracting two values measures the actual time that passed between two events. Contrast this with ProcessTimer that tries to measure only CPU time used by the current process.

Call Timer twice, and calculate the difference (in seconds) using the TimerSeconds. Like this:

var
  TimeStart: TTimerResult;
  Seconds: TFloatTime;
begin
  TimeStart := Timer;
  // ...  do something time-consuming ...
  Seconds := TimerSeconds(Timer, TimeStart);
  // or: Seconds := TimeStart.ElapsedTime;
  WritelnLog('Seconds passed: %f', [Seconds]);
end;

function TimerSeconds(const A, B: TTimerResult): TFloatTime;

Subtract two times obtained from Timer, A-B, return a difference in seconds.

function ProcessTimer: TProcessTimerResult;

Current time, local to this process. Use this to measure and compare the time it takes your program to do some calculations.

If possible, this measures only the CPU usage of this process. So it ignores delays caused by other processes doing something on your system, and it ignores things like waiting for hard disk (I/O). This is possible on Unix thanks to the clock API, see http://www.gnu.org/software/libc/manual/html_node/Processor-And-CPU-Time.html . On other platforms (like Windows), this simply measures real time that passed.

You usually take two ProcessTimer values, subtract them with ProcessTimerSeconds, and this is the time that passed – in seconds. Like this:

var
  TimeStart: TProcessTimerResult;
  Seconds: TFloatTime;
begin
  TimeStart := ProcessTimer;
  // ...  do something time-consuming ...
  Seconds := ProcessTimerSeconds(ProcessTimer, TimeStart);
  // or: Seconds := TimeStart.ElapsedTime;
  WritelnLog('Seconds passed (in this process): %f', [Seconds]);
end;

function ProcessTimerNow: TProcessTimerResult; deprecated 'use ProcessTimer';

Warning: this symbol is deprecated: use ProcessTimer

 
function ProcessTimerSeconds(const a, b: TProcessTimerResult): TFloatTime;

Subtract two times obtained from ProcessTimer, A-B, return a difference in seconds.

procedure ProcessTimerBegin; deprecated 'instead of this, better to use a local variable, and ProcessTimer and ProcessTimerSeconds';

Warning: this symbol is deprecated: instead of this, better to use a local variable, and ProcessTimer and ProcessTimerSeconds

Simple measure of process CPU time. Call ProcessTimerBegin at the beginning of your calculation, call ProcessTimerEnd at the end. ProcessTimerEnd returns a float number, with 1.0 being one second.

Note that using this is unsafe in libraries, not to mention multi-threaded programs (it's not "reentrant") — you risk that some other code called ProcessTimerBegin, and your ProcessTimerEnd doesn't measure what you think. So in general units, do not use this, use ProcessTimer and ProcessTimerSeconds instead.

function ProcessTimerEnd: TFloatTime; deprecated 'instead of this, better to use a local variable, and ProcessTimer and ProcessTimerSeconds';

Warning: this symbol is deprecated: instead of this, better to use a local variable, and ProcessTimer and ProcessTimerSeconds

 
function Profiler: TCastleProfiler;

Single instance of TCastleProfiler that you can use for all profiling. Castle Game Engine uses it to report loading times of various assets automatically.

function FrameProfiler: TCastleFrameProfiler;

Single instance of TCastleFrameProfiler that you can use for frame profiling. See TCastleFrameProfiler for more documentation and examples. Castle Game Engine uses this to report render/update times automatically.

function CastleNow: TDateTime;

Just like standard Now function, but works on all platforms supported by CGE. On Nintendo Switch the standard function will crash now.

function CastleToday: TDateTime;

Just like standard Today function, but works on all platforms supported by CGE. On Nintendo Switch the standard function will crash now.

function CastleYesterday: TDateTime;

Just like standard Yesterday function, but works on all platforms supported by CGE. On Nintendo Switch the standard function will crash now.

function CastleTomorrow: TDateTime;

Just like standard Tomorrow function, but works on all platforms supported by CGE. On Nintendo Switch the standard function will crash now.

procedure CastleRandomize;

Just like standard Randomize function, but works on all platforms supported by CGE. On Nintendo Switch the standard function will crash now. Note that you seldom need to call this explicitly: CastleUtils calls it already in the initialization.

Types

TFloatTime = Double;

Time in seconds. This is used throughout my engine to represent time as a floating-point value with good accuracy in seconds.

Using the "double" precision (not just "single") is good to guarantee good accuracy. It is also the precision required for storing time in X3D. See also: https://randomascii.wordpress.com/2012/02/13/dont-store-that-in-a-float/ https://twitter.com/ID_AA_Carmack/status/418158611664097280

To test that "single" is not enough, open some animation in view3dscene, and change "on display" time pass to 1000. It goes even better if AutoRedisplay is False, and LimitFps is 0.0, and model is still for some time — then we do many OnUpdate calls with very small SecondsPassed values.

TMilisecTime = QWord deprecated 'To measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds' ;

Warning: this symbol is deprecated: To measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds

To measure time, better use Timer + TimerSeconds or ProcessTimer + ProcessTimerSeconds

TFrameId = QWord;

Part of CastleTimeUtils unit: TFramesPerSecond.

TFrameMetric = (...);

Part of CastleTimeUtils unit: TCastleFrameProfiler.

Values
  • fmBeforeRender
  • fmRender
  • fmRenderTransform
  • fmRenderScene
  • fmRenderShapesFilterBlending
  • fmUpdate: fmRenderFrameProfiler,
  • fmUpdateScene
  • fmUpdatePhysics

Constants

OldestTime = -MaxDouble;
 
MinDateTime: TDateTime = MinDouble;
 

Generated by PasDoc 0.15.0.