首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::time::持续时间是否与“时间”箱中的time::precise_time_ns一样精确?

std::time::持续时间是否与“时间”箱中的time::precise_time_ns一样精确?
EN

Stack Overflow用户
提问于 2019-04-09 00:25:22
回答 1查看 1.5K关注 0票数 8

长期以来,time板条箱及其time::precise_time_ns功能一直是精确测量锈蚀时间的标准方法。但是,现在不推荐time机箱,而std库有用于度量所用时间的std::time::Instant

我不确定它有同样的精度,至少从设计上看是这样的。我知道这可能是一个模糊的问题,因为对于不同的OSes,这两种事物都有不同的实现,而且实现可能在不同的版本中发生变化,但至少它们有相同的目的吗?至少从设计的角度来看,std::time::Durationtime::precise_time_ns的正确替代品吗?

在我的系统(Mac )上运行这个脚本会输出相当小的持续时间,所以它可能非常精确:

代码语言:javascript
复制
use std::time::Instant;

fn main() {
    let mut t = Instant::now();
    loop {
        println!("{:?}", t.elapsed());
        t = Instant::now();
    }
}
代码语言:javascript
复制
40ns
42ns
41ns
45ns
40ns
41ns
40ns
40ns
41ns
41ns
41ns
40ns
40ns
40ns
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-10 19:10:38

是的,具有很高的确定性,std::time::Instanttime::precise_time_ns的正确替代品,具有相同或更好的精度。

在Rust 1.33.0、time 0.1.41中,大多数OSes of time::precise_time_ns()std::time::Instant::now()的实现是相同的,很少有例外。

  • Unix:同,clock_gettime(CLOCK_MONOTONIC, ...)
  • MacOS:相同,mach_absolute_time
  • :相同,QueryPerformanceCounter
  • Wasm32time没有实现,std使用TimeSysCall::perform(TimeClock::Monotonic)
  • 氧化还原:相同,与unix相同
  • SGX:实现不同,可能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")))]

代码语言:javascript
复制
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")))]

代码语言:javascript
复制
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"))]

代码语言:javascript
复制
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"))]

代码语言:javascript
复制
Instant { t: unsafe { libc::mach_absolute_time() } }

视窗

这两种实现都使用QueryPerformanceCounter

时间

#[cfg(windows)]

代码语言:javascript
复制
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)]

代码语言:javascript
复制
let mut t = Instant { t: 0 };
cvt(unsafe {
    c::QueryPerformanceCounter(&mut t.t)
}).unwrap();
t

Wasm32

它可能是用于非网络使用,与万维网无关。它time机箱,它没有实现。

时间

#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]

代码语言:javascript
复制
unimplemented!()

标准

#[cfg(target_arch = "wasm32")]

代码语言:javascript
复制
Instant(TimeSysCall::perform(TimeClock::Monotonic))

氧化还原

这两种实现都使用clock_gettime(CLOCK_MONOTONIC, ...),与unux相同。

时间

#[cfg(target_os = "redox")]

代码语言:javascript
复制
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")]

代码语言:javascript
复制
Instant { t: now(syscall::CLOCK_MONOTONIC) }

SGX

这里的实现是不同的。time机箱回到std,并使用非单调时间(可能当时在std中没有单调时间)。从时间迁移到std可能会提高准确性,因为它使用的是SGX特定的调用。

时间

#[cfg(target_env = "sgx")]

代码语言:javascript
复制
// 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"))]

代码语言:javascript
复制
Instant(usercalls::insecure_time())
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55583503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档