The ultra-short variant of what is going on:<p>Time in Erlang was historically used for many things: What time is it? How much time elapsed between points A and B? Give me time, use it as a unique timestamp. And so on.<p>The old way Erlang handled time (with time correction enabled) was to speed up or slow down the internal clock by about 1% whenever the system time changed. This is fine for smaller fluctuations like leap seconds (and correspond nicely to what Google calls leap-second-smearing). But for a large sudden "time warp", the system will be wrong forever because it will never catch up. The 1% frequency difference also means that 1000ms is closer to 990ms or 1010ms.<p>The new API maintains a precise and accurate monotonic clock which is used to wait on timers, do latency calculations and such. And then a "system time" is kept by noting how the system time is "offset" from the internal monotonic clock. You can monitor time change events of this "system" time, which allows your program to explicitly handle leap seconds, or when the system suddenly gets full NTP connectivity and learns that 14 days has passed since last reboot.<p>Finally, a seperate API can give unique integers. Earlier, erlang:now() was guaranteed unique (even if called from several different processes at the same time. It would simply "speed up" for a while if the calls were too close to each other). The downside of this guarantee was a big fat lock around erlang:now(), which has been dreadful to anyone who wanted good scalability in their programs. Lock instrumentation could often show serious contention around this lock.<p>By querying the underlying OS for the best clock source and separating the different time concepts, timer wheels can now be per-core, which results in a massive scalability boost of the system as a whole.<p>All in all, it is a necessary and very cool change to Erlang systems. It allows one to handle time with the attention to detail which is needed. While the original leap-smearing tactic is fine (and worked well for a long time), this finally allows people to program real solutions to leap seconds and sudden NTP time warps.<p>(Edit: added a "never" which was needed for a sentence to parse correctly).
<i>The system clock on such a system will typically be way off when the system boots. If the no time warp mode is used, and the Erlang runtime system is started before the OS system time has been corrected, the Erlang system time may be wrong for a very long time, even centuries or more.</i><p>There's something incredibly badass about Erlang/OTP's documentation addressing the idea of an OTP app running for "centuries or more".
That looks like a well thought out and engineered approach to handle time. Often it left unspecified what happens when time warps. And there a certainly a lot of interesting corner cases.<p>I've seen system misbehave very badly during time warps. Even if NTP is configured sometimes it will snap the time instead of slewing it.<p>It is always fun when there is a time delta measurement on absolute time and it moves backwards. Now dt is negative with all kind of wonderful and exciting ramifications "Oh so we are sleeping for 4294967294 seconds, great!"
Cool:<p><pre><code> erlang:unique_integer([monotonic])
</code></pre>
I wish this was a more common API function. Being able to do ordering without having to think about time and concurrency is <i>really</i> nice (I know x86 has an interlocked increment that you could just use on an arbitrary global variable, but that means that you're not safe across crashes).