Wall Clock vs Monotonic Clock (墙上时钟 vs 单调时钟)
墙上时钟指的是我们日常意义上的时间,正如墙上的时钟代表的时间一样。单调时钟指的是某个时间点后开始计算的时间,单纯意义上的代表的时间是没有意义的。
操作系统上相对应的提供了两套时间,分别对应墙上时钟和单调时钟,操作系统用UTC来代表墙上时钟,UTC不支持闰秒, 并且可以认为更改,而且操作系统的时间是通过石英钟等来实现的,会由于温度等不可控因素导致时间发生偏移,
往往会通过网络时间协议NTP来进行同步,因此UTC天然存在着较大的误差,对于某些高性能场景的精准时间计算是不够的。
相对的,单调时钟保证时间一定是单调递增的,不存在时间往回拨。
Go语言怎么用单调时间计算花费时间
Go语言Time 结构体就定义了单调始终
type Time struct {
// wall and ext encode the wall time seconds, wall time nanoseconds,
// and optional monotonic clock reading in nanoseconds.
//
// From high to low bit position, wall encodes a 1-bit flag (hasMonotonic),
// a 33-bit seconds field, and a 30-bit wall time nanoseconds field.
// The nanoseconds field is in the range [0, 999999999].
// If the hasMonotonic bit is 0, then the 33-bit field must be zero
// and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext.
// If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit
// unsigned wall seconds since Jan 1 year 1885, and ext holds a
// signed 64-bit monotonic clock reading, nanoseconds since process start.
wall uint64
ext int64
...
wall代表墙上始终,ext 代表单调时钟。
time.Sub内部先根据ext计算,如果没有ext,则根据UTC计算
func (t Time) Sub(u Time) Duration {
if t.wall&u.wall&hasMonotonic != 0 {
te := t.ext
ue := u.ext
d := Duration(te - ue)
if d < 0 && te > ue {
return maxDuration // t - u is positive out of range
}
if d > 0 && te < ue {
return minDuration // t - u is negative out of range
}
return d
}
d := Duration(t.sec()-u.sec())*Second + Duration(t.nsec()-u.nsec())
// Check for overflow or underflow.
switch {
case u.Add(d).Equal(t):
return d // d is correct
case t.Before(u):
return minDuration // t - u is negative out of range
default:
return maxDuration // t - u is positive out of range
}
}
大概是根据单调时间来计算花费的时间。
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
time.Sleep(time.Second)
fmt.Printf("have past %f seconds.", time.Since(t).Seconds())
}
rust语言怎么计算单调时间
使用std::Instant:now()
use std::time::{Duration, Instant};
use std::thread::sleep;
fn main() {
let now = Instant::now();
sleep(Duration::new(2, 0));
println!("{}", now.elapsed().as_secs());
}
第三方库提供了更高性能的实现,有Coarse Time的实现coarsetime::Instant::now()
以及基于Time Stamp Counter(TSC)寄存器的tikv/minstant
库。