Да, с высокой степенью достоверности, std::time::Instant
- правильная замена для time::precise_time_ns
, имеющая такую же или лучшую точность.
Начиная с Rust 1.33.0, time
0.1.41, реализации для большинства операционных систем time::precise_time_ns()
и std::time::Instant::now()
одинаковы, за некоторыми исключениями.
- Unix : То же ,
clock_gettime(CLOCK_MONOTONIC, ...)
- MacOS : то же ,
mach_absolute_time
- Windows : То же ,
QueryPerformanceCounter
- Wasm32 :
time
не имеет реализации, std
использует TimeSysCall::perform(TimeClock::Monotonic)
- Redox : такой же , такой же как unix
- SGX : реализации отличаются , вероятно
std
имеет более правильную реализацию
Маловероятно, что в будущих версиях реализация std::time::Instant::now
ухудшится.
Подробности реализации
time
crate имеет все реализации в одном файле , с флагами cfg, в стандартной библиотеке есть каталог на систему, с mod.rs, где реализация выбирается во время компиляции (unix также есть условная компиляция для Mac OS внутри time.rs
).
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, ...)
работает и на моей системе, Mac OS 10.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() } }
Windows
Обе реализации используют 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();
t
Wasm32
Это, вероятно, не для веб-использования и не связано с web-sys . Это time
Ящик не реализован.
время
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
unimplemented!()
станд
#[cfg(target_arch = "wasm32")]
Instant(TimeSysCall::perform(TimeClock::Monotonic))
Redox
Обе реализации используют 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
Ящик возвращается к стандартному стандарту и использует немонотонное время (в то время стандартное время не было, вероятно, в стандартном режиме). Вероятно, переход от времени к стандартному стандарту повышает точность, поскольку он использует специфичный для 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())