长期以来,time板条箱及其time::precise_time_ns功能一直是精确测量锈蚀时间的标准方法。但是,现在不推荐time机箱,而std库有用于度量所用时间的std::time::Instant。
我不确定它有同样的精度,至少从设计上看是这样的。我知道这可能是一个模糊的问题,因为对于不同的OSes,这两种事物都有不同的实现,而且实现可能在不同的版本中发生变化,但至少它们有相同的目的吗?至少从设计的角度来看,std::time::Duration是time::precise_time_ns的正确替代品吗?
在我的系统(Mac )上运行这个脚本会输出相当小的持续时间,所以它可能非常精确:
use std::time::Instant;
fn main() {
let mut t = Instant::now();
loop {
println!("{:?}", t.elapsed());
t = Instant::now();
}
}40ns
42ns
41ns
45ns
40ns
41ns
40ns
40ns
41ns
41ns
41ns
40ns
40ns
40ns发布于 2019-04-10 19:10:38
是的,具有很高的确定性,std::time::Instant是time::precise_time_ns的正确替代品,具有相同或更好的精度。
在Rust 1.33.0、time 0.1.41中,大多数OSes of time::precise_time_ns()和std::time::Instant::now()的实现是相同的,很少有例外。
clock_gettime(CLOCK_MONOTONIC, ...)mach_absolute_timeQueryPerformanceCountertime没有实现,std使用TimeSysCall::perform(TimeClock::Monotonic)std有更正确的实现。在未来的版本中,std::time::Instant::now实现不太可能恶化。
实现细节
所有实现都在单个文件中。,带有cfg标志,标准库每个系统都有目录,在编译时选择实现的mod.rs (unix还为time.rs内的mac提供了条件编译)。
Unix,“正则”,而不是MacOS或iOS
这两种实现都使用clock_gettime (3)和CLOCK_MONOTONIC clock_id。
时间
#[cfg(all(not(target_os = "macos"), not(target_os = "ios")))]
let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 };
unsafe {
libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut ts);
}
(ts.tv_sec as u64) * 1000000000 + (ts.tv_nsec as u64)标准
#[cfg(unix)] + #[cfg(not(any(target_os = "macos", target_os = "ios")))]
Instant { t: now(libc::CLOCK_MONOTONIC) }Unix、MacOS或iOS
这两种实现都使用mach_absolute_time。
顺便说一句,标准clock_gettime(CLOCK_MONOTONIC, ...)也在我的系统上工作,MacOS10.13.6,但我不确定它是否真的是单调的。
时间
#[cfg(any(target_os = "macos", target_os = "ios"))]
unsafe {
let time = libc::mach_absolute_time();
let info = info();
time * info.numer as u64 / info.denom as u64
}标准
#[cfg(unix)] + #[cfg(any(target_os = "macos", target_os = "ios"))]
Instant { t: unsafe { libc::mach_absolute_time() } }视窗
这两种实现都使用QueryPerformanceCounter
时间
#[cfg(windows)]
let mut ticks = i64_to_large_integer(0);
unsafe {
assert!(QueryPerformanceCounter(&mut ticks) == 1);
}
mul_div_i64(large_integer_to_i64(ticks), 1000000000, frequency()) as u64标准
#[cfg(windows)]
let mut t = Instant { t: 0 };
cvt(unsafe {
c::QueryPerformanceCounter(&mut t.t)
}).unwrap();
tWasm32
它可能是用于非网络使用,与万维网无关。它time机箱,它没有实现。
时间
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
unimplemented!()标准
#[cfg(target_arch = "wasm32")]
Instant(TimeSysCall::perform(TimeClock::Monotonic))氧化还原
这两种实现都使用clock_gettime(CLOCK_MONOTONIC, ...),与unux相同。
时间
#[cfg(target_os = "redox")]
let mut ts = syscall::TimeSpec { tv_sec: 0, tv_nsec: 0 };
syscall::clock_gettime(syscall::CLOCK_MONOTONIC, &mut ts).unwrap();
(ts.tv_sec as u64) * 1000000000 + (ts.tv_nsec as u64)标准
#[cfg(target_os = "redox")]
Instant { t: now(syscall::CLOCK_MONOTONIC) }SGX
这里的实现是不同的。time机箱回到std,并使用非单调时间(可能当时在std中没有单调时间)。从时间迁移到std可能会提高准确性,因为它使用的是SGX特定的调用。
时间
#[cfg(target_env = "sgx")]
// This unwrap is safe because current time is well ahead of UNIX_EPOCH, unless system clock is adjusted backward.
let std_duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
std_duration.as_secs() * NANOS_PER_SEC + std_duration.subsec_nanos() as u64标准
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
Instant(usercalls::insecure_time())https://stackoverflow.com/questions/55583503
复制相似问题