Talking about time correction system from Erlang time function

Source: Internet
Author: User

Many people will notice this problem, Erlang provides 2 time functions, Erlang:now () and Os:timestamp (). In the same way, the current time is returned. The time is from January 1, 1970 Zero, to the current elapsed time, the result is {megasecs, Secs, microsecs}.
What is the difference between these two functions?
Os:timestamp () Gets the time of the operating system without making any corrections, while Erlang:now () ensures that a unique time is generated for each fetch, that is, Erlang:now () makes a correction to the time on the implementation, Each time a monotonic forward unique value is generated.
features of Erlang:now ():
Monotonic
Erlang:now () never jumps backwards-it always moves forward
Interval correct
The
interval between-Erlang:now () calls is expected-correspond to the correct time in real life (as defined B Y an atomic clock, or better)
Absolute Correctness
the erlang:now/0 value should is possible to convert to a absolute and correct date-time, corresponding to the real World Date and time (the wall clock)
System Correspondence
The
erlang:now/0 value converted to a date-time are expected to correspond to times given by and programs on the SY Stem (or by functions like os:timestamp/0)
Unique
No calls to Erlang:now on one Erlang node should return the same value

The main features are these 3:
Characteristics Description
monotone forward erlang:now () Gets the time is monotonous forward, even if the system time goes backwards, It does not affect the use of this function. (Time is still forward, almost without bias)
uniqueness erlang:now () the values obtained are unique, 2 Identical values are not repeated.
Interval correction The interval of two erlang:now () calls can be exploited to correct erlang time.
Here, we can see that Erlang implements a set of time-correction mechanisms, which are corrected when the system time goes wrong. (for this piece of content, you can see Erlang related documents time correction)
Erlang Time CorrectionThe role of time correction:before starting this section, talk about the role of time correction 1. Time is monotonous forward:For example, explain the problem of time reversal:For example, the game will count the total number of kills today and yesterday, cross 0 o'clock to write the number of today's killer field to yesterday's field, and then set the 0 today. After 0 points, if the time goes backwards for a few seconds, then it repeats across 0 points. Today's numbers, then, will cover yesterday's numbers, causing the number to be zeroed out yesterday.
2. Time is smooth:The same example illustrates the problem of time instability:For example, in Erlang development, there is often a process call another process scene, usually 5 seconds timeout, if the time suddenly accelerated for 5 seconds, the equivalent of no wait for the operation to complete, the direct timeout. Of course, it's unreasonable.
features of Erlang time correction:
Monotonic
The
clock should not move backwards
Intervals should is near the truth
We want the actual time (as measured by a atomic clock or an astronomer) that passes between and time stamps, T1 an D T2, to is as near to t2-t1 as possible.
Tight coupling to the wall clock
We want a timer that's fired when the wall clock reaches a time on the future, to the fire as near
in time as possible
if the operating system time changes, Erlang does not immediately change the internal time to the system time, but the time is slightly faster or slower, and ultimately consistent with the system time. Even if the system time suddenly goes backwards to a previous time, but the time is always forward this will not change, so, Erlang is only expected in the future at some time and the system time to agree, but not to reverse the time.
How does Erlang correct the time? Erlang internal time will be synchronized with the system wall clock time, when the system clock time suddenly change, Erlang will compare two time differences, so that the internal time synchronization value slightly larger or smaller, the maximum amplitude is 1%, that is, when the system time changed 1 minutes, Erlang takes 100 minutes to adjust slowly and eventually stays in sync with the system time.
what functions are affected by time correction?
erlang:now/0
the infamous erlang:now/0 function uses time correction so, differences between, "Now-timestamps" would corres Pond 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 C orrected time.
ERLANG:START_TIMER/3 and ERLANG:SEND_AFTER/3
the timer BIF ' s work with corrected time, so that they would not fire prematurely or too late due to changes in the W All clock time.


Source AnalysisErlang:now () is the BIF implementation, the code is as follows: (Take R16B02 as an example)
/* * BIF.C now_0 function, implement erlang:now/0 * return a timestamp */bif_rettype now_0 (bif_alist_0) {    Uint megasec, sec, microsec;    eterm* hp;    Get_now (&megasec, &sec,μsec); Get current time    hp = Halloc (bif_p, 4);    Bif_ret (TUPLE3 (HP, Make_small (MEGASEC), Make_small (sec),   Make_small (microsec)));//return {megasecs, Secs, Microsecs }}
Then look at the Get_now () function.
/* * erl_time_        Sup.c Get_now function, gets the current time * get a timestamp */void get_now (uint* megasec, uint* sec, uint* microsec) {systimeval now;        Erts_smp_mtx_lock (&ERTS_TIMEOFDAY_MTX); Get_tolerant_timeofday (&now);  Gets the current time value do_erts_deliver_time (&now); Record the current time (for the VM to read the current time, such as a timer)/* To make sure that the time is greater than the last acquired */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_se    C + +;        } then = Now;        Erts_smp_mtx_unlock (&ERTS_TIMEOFDAY_MTX);    *megasec = (Uint) (now.tv_sec/1000000);    *sec = (Uint) (now.tv_sec% 1000000);    *microsec = (Uint) (NOW.TV_USEC); Update_approx_time (&now);//Update "brief" time (only for marking process start time)} 
The focus here is on the Get_tolerant_timeofday (), which realizes the time correction function.
/* * erl_time_sup.c get_tolerant_timeofday function, get current time * There are two implementations depending on the system API, one of which is to do a description */static void Get_tolerant_timeofday (    Systimeval *tv) {syshrtime diff_time, Curr;    if (erts_disable_tolerant_timeofday) {///time correction function is disabled, direct return to System time sys_gettimeofday (TV); return; } *TV = Inittv;     Take VM start time//Calculate the internal time from VM boot to now (positive, in microseconds) Diff_time = ((Curr = Sys_gethrtime ()) + hr_correction-hr_init_time)/1000;    if (Curr < Hr_init_time) {erl_exit (1, "unexpected behaviour from operating system High" "Resolution Timer"); }//Check if just corrected (two correction minimum interval 1s) if ((Curr-hr_last_correction_check)/> 1000000) {/* Check the correction need */sy Shrtime Tv_diff, Diffdiff; Systimeval Tmp;int done = 0;//calculates the actual time from the VM boot to the present (if the system time is adjusted, may be negative, in microseconds) Sys_gettimeofday (&tmp); Tv_diff = ( Syshrtime) tmp.tv_sec) * 1000000 + Tmp.tv_usec;tv_diff-= ((syshrtime) inittv.tv_sec) * 1000000 + Inittv.tv_usec;diffdiff = diff_time-tv_diff;//the difference between the actual time and the internal time (shortening this time difference to catch up with the actual times) if (Diffdiff > 10000) {//internal time faster than 0.01s outside time   Syshrtime Corr = (curr-hr_last_time)/100; Two calls elapsed actual time * 1% if (corr/1000 >= diffdiff) {++done;hr_correction-= ((syshrtime) diffdiff) * 1000;/* More than DIFFDI ff*1000 * 100, only fix diffdiff*1000, * is 1s need to spend 100s correction, while marking this correction completed * What will come here: This function has not been called for a long time, more than 100 times times the temporal bias * and then the mark correction is completed, There is no time skew */} else {hr_correction-= Corr;//correction value is two times the actual time elapsed * 1%}//the interval between the time of the VM startup Diff_time = (Curr + hr_correc Tion-hr_init_time)/1000;    } else if (Diffdiff <-10000) {//Internal time is 0.01s or more slower than external time syshrtime Corr = (curr-hr_last_time)/100;    if (corr/1000 >=-diffdiff) {++done;hr_correction-= ((syshrtime) diffdiff) * 1000;    } else {hr_correction + = Corr; } Diff_time = (Curr + hr_correction-hr_init_time)/1000; } else {/* internal time and external time offset within 0.01s, Mark Complete, wait for the remaining time after 1s correction * This code purpose is, if the time deviation in 0.01s, the VM deliberately wait 1s after correcting this time * In addition, if the time has not gone wrong, will come here, reduce Time function call cost */++done;}    if (done) {hr_last_correction_check = Curr;} } tv->tv_sec + = (int) (Diff_time/((syshrtime) 1000000));    Tv->tv_usec + = (int) (Diff_time% ((syshrtime) 1000000));    if (tv->tv_usec >= 1000000) {tv->tv_usec-= 1000000;tv->tv_sec + 1; } hr_last_time = Curr;}
here, Erlang uses a monotonically increasing time function, Sys_gethrtime (), as a reference to determine the actual time the VM actually experienced, and then slightly tilt the clock time to the system so that it will eventually stay in sync with the system clock time. As for Sys_gethrtime (), I have also prepared a bit of information to expand reading and sharing.


Expand Readinggethrtime ()the previously mentioned Sys_gethrtime (), is actually a macro (temporarily only discussed under Linux implementation, win under similar)
#define SYS_GETHRTIME () Gethrtime ()
About Gethrtime () can look at the official UNIX Document Description man page for Gethrtime, written in detail. Also, refer to C + + Reference Guide C + + Reference Guide-high Resolution timers
This is the two characteristics:1. Monotonous forward, not backwards2. Linear growth, does not become faster or slower
Therefore, the Erlang VM takes advantage of the hardware-based monotonic increment time, takes two time difference to calculate the VM running time, then take the operating system's wall clock time to compare, by gradually narrowing this time lag to realize the VM is always monotonous forward, so that the VM time to smoothly correct to the user's wall clock time. The smooth point here is that the time-correction mechanism of the VM will speed up or slow down the time "slightly", but the maximum is 1%, that is to say, the VM experience 1s may actually be 0.99s or 1.01s

Time SynchronizationHere you see the "Parallel and distributed simulation system" by the author of the relevant article synchronizing clocks? (Wallclock time), also a reference value

Concluding remarksFinally, the side effects of time correction are reported. Erlang Implementation Time correction has the computational overhead, and the intrinsic correction value is a global variable, not just all erlang processes, or the VM all scheduling threads will read and write this time, so there is a lock to ensure the data. To do this, Erlang internally sets the erlang:now/0 call frequency to be no more than 1 subtle 1 times. of course, if the acquisition time is for testing purposes only, or if the error log time is printed, it is entirely possible to replace it with os:timestamp/0. For some projects with large-scale processes, you can also set up some time management processes for synchronizing time, and each process simply reads its own process dictionary.
You can also disable this feature if you do not want to use it. Time correction is enabled or disabled by passing, the +c [true|false] command line argument to Erl.

after R18, Erlang provides more time to calibrate the associated APIs, exposing the user to the value of the underlying time, and the actual difference. There is no explanation for the moment. Link Address

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

Talking about time correction system from Erlang time function

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.