From 6487aac5977cf470bc6a2cd0964da2850ee38717 Mon Sep 17 00:00:00 2001
From: Rickard Green
Disable compensation for sudden changes of system time.
-Normally,
When the
NOTE: You can check whether the adjustment is enabled or
- disabled by calling
-
Enable or disable
+
Enable time correction. This is the default if + time correction is supported on the specific platform.
Disable time correction.
For backwards compatibility, the boolean value can be omitted.
+ This is interpreted as
Set
+
See
See
Currently supported time unit representations:
+Time unit expressed in parts per second. That is,
+ the time unit equals
Symbolic representation of the time unit
+ represented by the integer
Symbolic representation of the time unit
+ represented by the integer
Symbolic representation of the time unit
+ represented by the integer
Symbolic representation of the time unit
+ represented by the integer
Symbolic representation of the native time unit + used by the Erlang runtime system.
+ +The
One can get an approximation of the
The value of the
The
Converts the
You may lose accuracy and precision when converting
+ between time units. In order to minimize such loss, collect all
+ data at
Returns an almost unique reference.
-The returned reference will re-occur after approximately 2^82 - calls; therefore it is unique enough for practical purposes.
--> make_ref(). -#Ref<0.0.0.135>+
Return a
Known issue: When a node is restarted multiple + times with the same node name, references created + on a newer node can be mistaken for a reference + created on an older node with the same node name.
The calling process starts monitoring
Currently only processes can be monitored, i.e. the only
- allowed
The pid of the process to monitor.
-A tuple consisting of a registered name of a process and
- a node name. The process residing on the node
The process locally registered as
When a process is monitored by registered name, the process
- that has the registered name at the time when
-
Send a monitor request of type
{Tag, MonitorRef , Type , Object, Info}
+ The monitor request is an asynchronous signal. That is, it + takes time before the signal reach its destination.
Currently valid
Monitor the existence of the process identified by
+
The process identifier of the process to monitor.
+A tuple consisting of a registered name of a process and
+ a node name. The process residing on the node
The process locally registered as
When a process is monitored by registered name, the + process that has the registered name at the time when the + monitor request reach its destination will be monitored. The monitor will not be effected, if the registered name is - unregistered.
-A
-{'DOWN', MonitorRef, Type, Object, Info}
- where
A reference to the monitored object:
-Either the exit reason of the process,
If/when
The monitoring is turned off either when the
If an attempt is made to monitor a process on an older node
- (where remote process monitoring is not implemented or one
- where remote process monitoring by registered name is not
- implemented), the call fails with
Making several calls to
The monitor is triggered either when the monitored process + terminates, is non existing, or if the connection to it is + lost. In the case the connection to it is lost, we do not know + if it still exist or not. After this type of monitor has been + triggered, the monitor is automatically removed.
+When the monitor is triggered a
{'DOWN', MonitorRef, Type, Object, Info}
+ where
equals:
+Either the exit reason of the process,
The monitoring is turned off either when the
If an attempt is made to monitor a process on an older node
+ (where remote process monitoring is not implemented or one
+ where remote process monitoring by registered name is not
+ implemented), the call fails with
The format of the
Monitor changes in
+
The monitor is triggered when the time offset is changed.
+ This either if the time offset value is changed, or if the
+ offset is changed from preliminary to final during
+
If the runtime system is in
+
The monitor will not be automatically removed + after it has been triggered. That is, repeated changes of + the time offset will trigger the monitor repeatedly.
+ +When the monitor is triggered a
{'CHANGE', MonitorRef, Type, Item, NewTimeOffset}
+ where
When the
Making several calls to
The monitor functionality is expected to be extended. That is,
+ other
The format of the
If/when
Returns the current
+
This is a
+
Different runtime system instances will use different
+ unspecified points in time as base for their Erlang monotonic clocks.
+ That is, it is pointless comparing monotonic times from
+ different runtime system instances. Different runtime system instances
+ may also place this unspecified point in time different relative
+ runtime system start. It may be placed in the future (time at start
+ will be a negative value), the past (time at start will be a
+ positive value), or the runtime system start (time at start will
+ be zero). The monotonic time as of runtime system start can be
+ retrieved by calling
+
Returns the current
+
Same as calling
+
This function is deprecated! Do not use it!
+ See the users guide chapter
+
Returns the tuple
It can only be used to check the local time of day if the time-zone info of the underlying operating system is properly configured.
-If you do not need the return value to be unique and
- monotonically increasing, use
-
Returns the old value of the flag.
Finalizes the
Returns the old state identifier. That is, if:
+Returns various information about the current system @@ -6163,6 +6411,57 @@ ok documentation of versions in the system principles guide.
Returns a list containing information about the source of
+
In case
This tuple only exist if
Highest possible resolution of current
+ OS monotonic time source as parts per second. If
+ no resolution information can be retreived from
+ the OS,
Returns the default port parallelism scheduling hint used. For more information see the @@ -6288,6 +6587,11 @@ ok
Returns
The
Returns a string containing version number and
@@ -6311,12 +6615,64 @@ ok
(
Returns a boolean value indicating whether
+
Returns the state of the time offset:
+The time offset is preliminary, and will be changed
+ at a later time when being finalized. The preliminary time offset
+ is used during the preliminary phase of the
+
The time offset is final. This
+ either due to the use of the
+
The time offset is volatile. That is, it may
+ change at any time. This due to the
+
Returns a value identifying the
+
The
The
The
Returns whether compensation for sudden changes of system
- time is
See also
Returns whether a pre erts-7.0 backwards compatible compensation
+ for sudden changes of system time is
Returns current
+
Calling
This time is not a monotonically increasing time
+ in the general case. For more information, see the documentation of
+
Returns current
+
Calling
This time is not a monotonically increasing time
+ in the general case. For more information, see the documentation of
+
Returns the current time offset between
+
The time offset may or may not change during operation depending
+ on the
A change in time offset may be observed at slightly + different points in time by different processes.
+ +If the runtime system is in
+
Returns the current time offset between
+
Same as calling
+
Returns current
+
The
+timestamp() ->
+ ErlangSystemTime = erlang:system_time(micro_seconds),
+ MegaSecs = ErlangSystemTime div 1000000000000,
+ Secs = ErlangSystemTime div 1000000 - MegaSecs*1000000,
+ MicroSecs = ErlangSystemTime rem 1000000,
+ {MegaSecs, Secs, MicroSecs}.
+ It however use a native implementation which does + not build garbage on the heap and with slightly better + performance.
+ +This time is not a monotonically increasing time
+ in the general case. For more information, see the documentation of
+
Generates and returns an
+
Generates and returns an
+
By default, i.e. when
Currently valid
Return only positive integers.
+Note that by passing the
Return
+
These values can be used when ordering events
+ on the runtime system instance. That is, if both
+
Strictly monotonically increasing values
+ are inherently quite expensive to generate and scales
+ poorly. This since the values needs to be
+ synchronized. That is, do not pass the
All currently valid
Note that the set of integers returned by
+
Failures:
+As of OTP 18 (ERTS version 7.0) the time functionality of
+ Erlang has been extended. This both includes a
+
The
In order to make it easier to understand this document we first + define some terminology. This is a mixture of our own terminology + (Erlang/OS system time, Erlang/OS monotonic time, time warp) + and globally accepted terminology.
+ +In a monotonically increasing sequence of values, all values + that have a predecessor are either larger than, or equal to its + predecessor.
+In a strictly monotonically increasing sequence of values, + all values that have a predecessor are larger than its + predecessor.
+Universal Time. Based on the rotation of the earth. Conceptually + mean solar time at 0° longitude.
+Coordinated Universal Time. UTC almost align with
+
Time since
+
The operating systems view of
+
A monotonically increasing time provided by the operating
+ system. This time does not leap and have a relatively steady
+ frequency although not completely correct. However, it is not
+ uncommon that the OS monotonic time stops if the system is
+ suspended. This time typically increase since some unspecified
+ point in time that is not connected to
+
The Erlang runtime systems view of
+
A monotonically increasing time provided by the
+ Erlang runtime system. The Erlang monotonic time increase since
+ some unspecified point in time. It can be retrieved by calling
+
Internally in the runtime system the Erlang monotonic
+ time is the "time engine" that is used for more or less
+ everything that has anything to do with time. All timers
+ regardless of it is a
A time warp is a leap forwards or backwards in time.
+Time is vital to an Erlang program and, more importantly, correct time is vital to an Erlang program. As Erlang is a language with soft real time properties and we have the possibility to express @@ -83,192 +253,587 @@ microsecond resolution or much less, but generally it has a drift that is not to be ignored.
-So we have this monotonic ticking and we have the wall clock - time. Two unreliable times that together can give us an estimate of - an actual wall clock time that does not jump around and that - monotonically moves forward. If the tick counter has a high - resolution, this is fairly easy to do, if the counter has a low - resolution, it's more expensive, but still doable down to - frequencies of 50-60 Hz (of the tick counter).
- -So the corrected time is the nearest approximation of an atomic - clock that is available on the computer. We want it to have the - following properties:
-To meet all the criteria, we have to utilize both times in such a - way that Erlangs "corrected time" moves slightly slower or slightly - faster than the wall clock to get in sync with it. The word - "slightly" means a maximum of 1% difference to the wall clock time, - meaning that a sudden change in the wall clock of one minute, takes - 100 minutes to fix, by letting all "corrected time" move 1% slower - or faster.
- -Needless to say, correcting for a faulty handling of daylight - saving time may be disturbing to a user comparing wall clock - time to for example calendar:now_to_local_time(erlang:now()). But - calendar:now_to_local_time/1 is not supposed to be used for presenting wall - clock time to the user.
- -Time correction is not perfect, but it saves you from the havoc - of clocks jumping around, which would make timers in your program - fire far to late or far to early and could bring your whole system - to it's knees (or worse) just because someone detected a small error - in the wall clock time of the server where your program runs. So - while it might be confusing, it is still a really good feature of - Erlang and you should not throw it away using time functions which - may give you higher benchmark results, not unless you really know - what you're doing.
+Time correction means that Erlang estimates a time from current - and previous settings of the wall clock, and it uses a fairly - exact tick counter to detect when the wall clock time has jumped - for some reason, slowly adjusting to the new value.
- -In practice, this means that the difference between two calls - to time corrected functions, like erlang:now(), might differ up to - one percent from the corresponding calls to non time corrected - functions (like os:timestamp()). Furthermore, if comparing - calendar:local_time/0 to calendar:now_to_local_time(erlang:now()), - you might temporarily see a difference, depending on how well kept your - system is.
- -It is important to understand that it is (to the program) - always unknown if it is the wall clock time that moves in the - wrong pace or the Erlang corrected time. The only way to determine - that, is to have an external source of universally correct time. If - some such source is available, the wall clock time can be kept - nearly perfect at all times, and no significant difference will be - detected between erlang:now/0's pace and the wall clock's.
- -Still, the time correction will mean that your system keeps - it's real time characteristics very well, even when the wall clock - is unreliable.
+If time correction is enabled, the Erlang runtime system
+ will make use of both
+
By default time correction will be enabled if support for
+ it on the specific platform exist. Support for it includes
+ both an OS monotonic time provided by the OS, and an
+ implementation in the Erlang runtime system utilizing the
+ OS monotonic time. You can check if your system has support
+ for OS monotonic time by calling
+
Time correction is enabled or disabled by passing the
+
If time correction is disabled, Erlang monotonic time + may warp forwards, it may stop and even freeze for extended + periods of time, and there are no guarantees that the frequency + of the Erlang monotonic clock is accurate or stable.
+ +You typically never want to disable time correction. + Previously there was a performance penalty associated with time + correction, but nowadays it is most often the other way around. + By disabling time correction you are likely to get bad scalability, + bad performance, and bad time measurements.
For all functionality where real time characteristics are - desirable, time correction is used. This basically means:
-All other functionality in the system where erlang:now/0 or any - other time corrected functionality is used, will of course - automatically benefit from it, as long as it's not "optimized" to - use some other time stamp function (like os:timestamp/0).
- -Modules like calendar and functions like erlang:localtime/0 use - the wall clock time as it is currently set on the system. They - will not use corrected time. However, if you use a now-value and - convert it to local time, you will get a corrected local time - value, which may or may not be what you want. Typically older code - tend to use erlang:now/0 as a wall clock time, which is usually - correct (at least when testing), but might surprise you when - compared to other times in the system.
+Time warp safe code is code that is able to handle
+ a time warp of
+
All uses of
erlang:now/0 is a function designed to serve multiple purposes - (or a multi-headed beast if you're a VM designer). It is expected - to hold the following properties:
-All these requirements are possible to uphold at the same - time if (and only if):
-The uniqueness property of erlang:now/0 is the most limiting - property. It means that erlang:now() maintains a global state and - that there is a hard-to-check property of the system that needs to - be maintained. For most applications this is still not a problem, - but a future system might very well manage to violate the - frequency limit on the calls globally. The uniqueness property is - also quite useless, as there are globally unique references that - provide a much better unique value to programs. However the - property will need to be maintained unless a really subtle - backward compatibility issue is to be introduced.
+Current
The time offset is determined at runtime system start
+ and will after this not change. This is the default behavior.
+ Not because it is the best mode (which it isn't). It is
+ default only because this is how the runtime system always
+ has behaved until ERTS version 7.0, and you have to ensure
+ that your Erlang code that may execute during a time warp is
+
Since the time offset is not allowed to change, time + correction needs to adjust the frequency of the Erlang + monotonic clock in order to smoothly align Erlang system + time with OS system time. A big downside of this approach + is that we on purpose will use a faulty frequency on the + Erlang monotonic clock if adjustments are needed. This + error may be as big as 1%. This error will show up in all + time measurements in the runtime system.
+ +If time correction is not enabled, the Erlang monotonic + time will freeze when the OS system time leap backwards. + The freeze of the monotonic time will continue until + OS system time catch up. The freeze may continue for + a very long time. When OS system time leaps forwards, + Erlang monotonic time will also leap forward.
+This mode is more or less a backwards compatibility mode + as of its introduction.
+On an embedded system it is not uncommon that the system
+ has no power supply at all, not even a battery, when it is
+ shut off. The system clock on such a system will typically
+ be way off when the system boots. If the
+
If you for some reason need to use Erlang code that
+ is not
+
Using the single time warp mode, the time offset is + handled in two phases:
+ +The preliminary phase starts when the runtime + system starts. A preliminary time offset based on + current OS system time is determined. This offset will + from now on be fixed during the whole preliminary phase.
+ +If time correction is enabled, the Erlang + monotonic clock will only use the OS monotonic time as + time source during this phase. That is, during the + preliminary phase changes in OS system time will have + no effect on Erlang system time and/or Erlang + monotonic time what so ever.
+ +If time correction is disabled, changes in OS system
+ time will effect the monotonic clock the same way as
+ when the
The final phase begin when the user finalize the time
+ offset by calling
+
During finalization, the time offset is adjusted and
+ fixated so that current Erlang system time align with
+ current OS system time. Since the time offset
+ may be changed, the Erlang system time may do
+ a time warp at this point. The time offset will from
+ now on be fixed until the runtime system terminates.
+ If time correction has been enabled, the time correction
+ also begins when this phase begins. When the system is
+ in the final phase it behaves exactly as in the
+
In order for this to work properly there are two + requirements that the user needs to ensure are + satisfied:
+ +The time warp made when finalizing the time offset + can only be done forwards without encountering problems. + This implies that the user has to ensure that the OS + system time is set to a time earlier or equal to actual + POSIX time before starting the Erlang runtime system. If + you are not completely sure the OS system time is correct, + set it to a time that is guaranteed to be earlier than + actual POSIX time before starting the Erlang runtime + system just to be safe.
The OS system time needs to be correct when the + the user finalizes the time offset.
If these requirements are not fulfilled, the system + may behave very bad. +
+ +Assuming that the requirements above are fulfilled, + time correction is enabled, and that the OS system time + is adjusted using some time adjustment protocol like NTP + or similar, only small adjustments of the Erlang monotonic + time should be needed in order to keep system times + aligned after finilization. As long as the system is not + suspended, the largest adjustments needed should be for + inserted (or deleted) leap seconds.
+ +In order to be able to use this mode you have
+ to ensure that all Erlang code that will execute in
+ both phases are
+
Code that only execute in the final phase does not have + to be able to cope with the time warp.
Multi time warp mode in combination with time + correction is the preferred configuration. This since, + on almost all platforms, the Erlang runtime system will have + better performance, will scale better, will behave better, + and since the accuracy, and precision of time measurements + will be better. Only Erlang runtime systems executing on + ancient platforms will benefit from another configuration.
+ +The time offset may change at any time without limitations. + That is, Erlang system time may perform time warps both + forwards and backwards at any time. Since we align + the Erlang system time with the OS system time by changing + the time offset, we can enable a time correction that tries + to adjust the frequency of the Erlang monotonic clock to be as + correct as possible. This will make time measurements using + the Erlang monotonic time more accurate and precise.
+ +If time correction is disabled, Erlang monotonic time + will leap forward if OS system time leaps forward. If the + OS system time leaps backwards, Erlang monotonic time will + stop briefly but it does not freeze for extended periods + of time. This since the time offset is changed in order to + align Erlang system time with OS system time.
+ +In order to be able to use this mode you have
+ to ensure that all Erlang code that will execute on the
+ runtime system is
+
The simple answer is to use erlang:now/0 for everything where - you want to keep real time characteristics, but use os:timestamp - for things like logs, user communication and debugging (typically - timer:ts uses os:timestamp, as it is a test tool, not a real world - application API). The benefit of using os:timestamp/0 is that it's - faster and does not involve any global state (unless the operating - system has one). The downside is that it will be vulnerable to wall - clock time changes.
+The old time API is based on
+
In order to be backwards compatible
Some of the new BIFs on some systems, perhaps surprisingly, + return negative integer values on a newly started run time + system. This is not a bug, but a memory usage optimization.
+ +The new API consists of a number of new BIFs:
+and a number of extensions of existing BIFs:
+The Erlang monotonic time as such is new as of ERTS + version 7.0. It has been introduced in order to be able + to detach time measurements such as elapsed time from + calender time. It is very common that one is interested + in measuring elapsed time or specifying a time relative + to another point in time without having any need to know + what the involved times are in UTC or any other + globally defined time scale. By introducing a time scale + that has a local definition of where it starts, it is + possible to manage time that do not concern calender + time on that time scale. Erlang monotonic time use + such a time scale with a locally defined start.
+ +The introduction of Erlang monotonic time gives us
+ the possibility to adjust the two Erlang times (Erlang
+ monotonic time and Erlang system time) separately. By
+ doing this, accuracy of elapsed time does not have to
+ suffer just because the system time happened to be
+ wrong at some point in time. Separate adjustments
+ of the two times are only performed in the time warp
+ modes, and only fully separated in the
+
The adjustment of system time could have been made + smother than using a time warp approach, but we think + that would be a bad choice. Since we are able to + express and measure time that aren't connected to + calender time by the use of Erlang monotonic time, it + is better to expose the change in Erlang system time + immediately. This since it makes it possible for the + Erlang applications executing on the system to react + on the change in system time as soon as possible. This + is also more or less exactly how most OSes handle this + (OS monotonic time and OS system time). By adjusting + system time smoothly we would just hide the fact that + system time changed and make it harder for the Erlang + applications to react to the change in a sensible way.
+ +In order to be able to react to a change in Erlang
+ system time you have to be able to detect that it
+ happened. The change in Erlang system time occurs when
+ current time offset is changed. We have therefore
+ introduced the possibility to monitor the time offset
+ using
+
{'CHANGE', MonitorReference, time_offset, clock_service, NewTimeOffset}
+ Besides reporting time
Previously
+ use
+ use
+
If you want the same format as returned by
+ take timestamps with
+ take timestamps with
+
Another easier way of doing this is to use
+
+ determine the order of events by saving a timestamp
+ with
+ determine the order of events by saving the integer
+ returned by
+
+ determine the order of events by saving a timestamp
+ with
+ determine the order of events by saving a tuple
+ containing
+
+Time = erlang:monotonic_time(),
+UMI = erlang:unique_integer([monotonic]),
+EventTag = {Time, UMI}
+ These tuples will be strictly monotonically ordered + on the current runtime system instance according to + creation time. Note that it is important that the + monotonic time is in the first element (the most + significant element when comparing 2-tuples). Using + the monotonic time in the tuples, you can calculate time + between events.
+If you are interested in the Erlang system time at the
+ time when the event occurred you can also save the time
+ offset before or after saving the events using
+
If you are executing in a mode where time offset + may change and you want to be able to get the actual + Erlang system time when the event occurred you can + save the time offset as a third element in the tuple + (the least significant element when comparing 3-tuples).
+
+ use the values returned from
+ use the value returned from
+
+ seed random number generation using
+ seed random number generation using a combination of
+
To sum this section up: Don't use
If, for some reason, time correction causes trouble and you are
- absolutely confident that the wall clock on the system is nearly
- perfect, you can turn off time correction completely by giving the
-
Your code may be required to be able to run on a variety
+ of OTP installations of different OTP releases. If so, you
+ can not just use the new API out of the box, since it will
+ not be available on old pre OTP 18 releases. The solution
+ is not to avoid using the new API, since your
+ code then won't be able to benefit from the scalability
+ and accuracy improvements made. Instead you want to use the
+ new API when available, and fall back on