From erlang time functions to the time correction system, erlang correction

Source: Internet
Author: User

From erlang time functions to the time correction system, erlang correction
Many people will notice this problem. erlang provides two time functions, erlang: now () and OS: timestamp (). In the same usage, the current time is returned. The specific time is counted from, January 1, January 1, 1970. The result is {MegaSecs, Secs, MicroSecs }.
What are the differences between these two functions?
OS: timestamp () indicates the time obtained by the operating system without any modification. erlang: now () ensures that a unique time is generated for each retrieval, that is, erlang: now () implements a correction for the time, and each time generates a unique monotonic forward value.
Erlang: now () features:

Monotonic
Erlang: now () never jumps backwards-it always moves forward
Interval correct
The interval between two erlang: now () CILS is expected to correspond to the correct time in real life (as defined by an atomic clock, or better)
Absolute correctness
The erlang: now/0 value shocould be possible to convert to an absolute and correct date-time, corresponding to the real world date and time (the wall clock)
System corresponsible
The erlang: now/0 value converted to a date-time is expected to correspond to times given by other programs on the system (or by functions like OS: timestamp/0)
Unique
No two callto erlang: now on one Erlang node shoshould return the same value

These three features are as follows:
Features Description
Monotonic forward Erlang: The time obtained by now () is monotonic forward. Even if the system time regresses, this function will not be affected. (The time is still forward, and there is almost no deviation from the previous one)
Uniqueness Erlang: the values obtained by now () are unique and two identical values are not repeated.
Interval correction The interval between two erlang: now () calls can be used to modify the erlang time.
Here, we can see that erlang implements a time correction mechanism internally. When the system time goes wrong, it will be corrected. (For more information, see the Erlang documentation time correction)
The role of erlang time correction: Before starting this section, let's talk about the role of time correction. 1. Time monotonic forward:For example, the problem of time regressing is described: for example, the game will count the total number of today and yesterday's kill fields, and the number of today's kill fields should be written to the field of yesterday when crossing the zero point, then set today's 0. After, if the time goes backwards for a few seconds, then it will be repeated across. The number of today will overwrite the number of yesterday, so that the number of yesterday is cleared.
2. Stable time:For example, in erlang development, one process often calls another process, which usually times out in five seconds, if the time suddenly increases by 5 seconds, it is equivalent to directly timeout without waiting for the Operation to complete. Of course this is unreasonable.
Erlang time correction features:
Monotonic
The clock shocould not move backwards
Intervals shoshould be near the truth
We want the actual time (as measured by an atomic clock or an astpolicmer) that passes between two time stamps, T1 and T2, to be as near to T2-T1 as possible.
Tight coupling to the wall clock
We want a timer that is to be fired when the wall clock reaches a time in the future, to fire as near to that point in time as possible

If the operating system time changes, erlang will not immediately change the internal time to the system time, but will speed up or slow down the time slightly, and eventually stay consistent with the system time. Even if the system time suddenly regresses to a previous time, but the time always goes forward, this will not change. Therefore, erlang only expects to reach an agreement with the system time at a certain time in the future, instead, it will not go backwards.
How does erlang correct the time? The internal time of erlang is synchronized with the system clock-up time. When the system clock-up time suddenly changes, erlang compares the two time differences to slightly increase or decrease the internal time synchronization value, the maximum range is 1%. That is to say, the VM may be 0.99 s or 1.01 s after 1 s. When the system time changes for one minute, erlang will spend 100 minutes to slowly correct and eventually stay in sync with the system time.
Which functions are affected by time correction?
Erlang: now/0
The infamous erlang: now/0 function uses time correction so that differences between two "now-timestamps" will correspond to other timeouts in the system. erlang: now/0 also holds other properties, discussed later.
Receive... after
Timeouts on receive uses time correction to determine a stable timeout interval.
The timer module
As the timer module uses other built in functions which deliver corrected time, the timer module itself works with corrected time.
Erlang: start_timer/3 and erlang: send_after/3
The timer BIF's work with corrected time, so that they will not fire prematurely or too late due to changes in the wall clock time.
More than erlang: now (), the above functions depend on the implementation of time correction. For example, erlang: send_after/3. Even if the system time changes, the messages sent by this function will be delivered within the predefined time range.
Source code analysis erlang: now () is a bif implementation, the Code is as follows: (take R16B02 as an example)
/** Bif. c now_0 function, implementing erlang: now/0 * return a timestamp */BIF_RETTYPE now_0 (BIF_ALIST_0) {Uint megasec, sec, microsec; Eterm * hp; get_now (& megasec, & sec, µsec); // obtain the current time hp = HAlloc (BIF_P, 4); BIF_RET (TUPLE3 (hp, make_small (megasec), make_small (sec ), make_small (microsec); // returns {MegaSecs, Secs, MicroSecs }}
Let's take a look at the get_now () function.
/** Erl_time_sup.c get_now function to obtain the current time * get a timestamp */void get_now (Uint * megasec, Uint * sec, Uint * microsec) {interval imeval now; erts_smp_mtx_lock (& erts_timeofday_ctx); get_tolerant_timeofday (& now); // get the current time value do_erts_deliver_time (& now); // record the current time (used for internal VM read current time, for example, timer)/* Make sure that the time is later than the obtained time */if (then. TV _sec> now. TV _sec | (then. TV _sec = now. TV _sec & then. TV _usec> = now. TV _usec) {now = then; now. TV _usec ++;}/* Check for carry from above + general reasonability */if (now. TV _usec> = 1000000) {now. TV _usec = 0; now. TV _sec ++;} then = now; erts_smp_mtx_unlock (& erts_timeofday_ctx); * megasec = (Uint) (now. TV _sec/1000000); * sec = (Uint) (now. TV _sec % 1000000); * microsec = (Uint) (now. TV _usec); update_approx_time (& now); // update the "Brief" Time (only used to mark the process start time )}
Here we will focus on get_tolerant_timeofday () and implement the time correction function.
/** Erl_time_sup.c handler function to obtain the current time * There are two implementations based on the system API. Here we take one of them as an illustration */static void get_tolerant_timeofday (SysTimeval * TV) {SysHrTime diff_time, curr; if (erts_disable_tolerant_timeofday) {// The time correction function is disabled and the system time sys_gettimeofday (TV); return ;}* TV = inittv; // obtain the VM startup time // calculate the internal time (positive value, in microseconds) that has elapsed since the VM was started (diff_time = (curr = sys_gethrtime () + hr_correction-hr_init_time) /1000; if (curr Here, erlang uses a monotonically increasing time function sys_gethrtime () as a reference to determine the actual time of the VM experience, and then slightly skews to the system clock time, as a result, the system will eventually synchronize the clock time. As for sys_gethrtime (), I have prepared some materials for further reading and sharing.



Extended reading the sys_gethrtime () mentioned earlier in gethrtime () is actually a macro (only the implementation in linux is discussed for the time being, and the implementation in win is similar)
#define sys_gethrtime() gethrtime()
For more information about gethrtime (), see the official unix documentation for man page for gethrtime. Gethrtime () is used to obtain the current time in real time. The precision is very high, in the unit of nanoseconds. However, two closely connected calls may return the same result, after all, the precision unit is nanoseconds, which ensures that the time will not go backwards. In addition, refer to C ++ Reference Guide-High Resolution Timers
That is, these two features: 1. monotonous forward, will not go backwards; 2. linear growth, will not become faster or slower. Each time scale goes through the same time.
Therefore, the Erlang VM calculates the VM running time based on the monotonically increasing time of the hardware and compares the difference between the two time points with the operating system's hanging clock time, by gradually narrowing the time difference, the VM time is always monotonic forward, so as to smoothly correct the VM time to the user's hanging time.

Synchronizing Clocks timing (Wallclock Time) is also useful for reference.
Assume that an interruption occurs every 30 milliseconds after 10 milliseconds. The increment time of each interruption is 29 milliseconds, and the correction is completed 10 times.

Finally, let's talk about the side effects of time correction. Erlang implements time correction with computing overhead, and the internal calibration value is a global variable, not only for all erlang processes, but also for all VM scheduling threads to read and write the time, so there must be a lock to ensure data. For this reason, erlang has set the erlang: now/0 call frequency to no more than 1 subtle once. Of course, if the acquisition time is only used for testing purposes, or the error log time can be printed, it can be replaced by OS: timestamp/0. For projects with large-scale processes, you can also set up some time management processes for time synchronization. Each process only needs to read its own process dictionary.
You can disable this function if you do not want to use it. Time correction is enabled or disabled by passing + C [true | false]Command line argument to erl.

After R18, erlang provides more time correction APIs to expose information about the underlying time to users. This is not explained at the moment. Link address

Reference: http://blog.csdn.net/mycwq/article/details/45346411

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.