-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SystemTime::now should use GetSystemTimePreciseAsFileTime where available #67266
Comments
Since I needed it for my own use, here is an example implementation that does the fallback on pre-Vista systems. #[cfg(windows)]
pub fn now() -> Instant {
use std::sync::atomic::{AtomicUsize, Ordering};
use winapi::shared::minwindef::{FILETIME, LPFILETIME};
use winapi::um::libloaderapi;
use winapi::um::sysinfoapi::GetSystemTimeAsFileTime;
static PTR: AtomicUsize = AtomicUsize::new(0);
// FIXME: not even sure if this atomic ordering stuff is needed.
// code adapted from https://github.com/rust-lang/rust/blob/master/src/libstd/sys/windows/compat.rs
let addr = match PTR.load(Ordering::SeqCst) {
0 => {
let module = b"kernel32\0".as_ptr() as *const i8;
let symbol = b"GetSystemTimePreciseAsFileTime\0".as_ptr() as *const i8;
let addr = unsafe {
let handle = libloaderapi::GetModuleHandleA(module);
match libloaderapi::GetProcAddress(handle, symbol) as usize {
0 => GetSystemTimeAsFileTime as usize, // fallback function
addr => addr,
}
};
PTR.store(addr, Ordering::SeqCst);
addr
}
addr => addr,
};
let ticks = unsafe {
let mut ft: FILETIME = std::mem::zeroed();
type PFNGSTAFT = unsafe extern "system" fn(LPFILETIME);
std::mem::transmute::<usize, PFNGSTAFT>(addr)(&mut ft as LPFILETIME);
std::mem::transmute::<FILETIME, u64>(ft) - 116444736000000000
};
Instant::from_ticks(ticks)
} |
|
XP will likely be split off into it's own target, so fallback won't be needed if that happens (#66801) |
|
I opened a PR #69858 for this. |
std: on Windows, use GetSystemTimePreciseAsFileTime if it is available This implements rust-lang#67266.
I think this can be closed now that #69858 is merged. |
The current implementation of std::time::SystemTime::now on Windows uses the GetSystemTimeAsFileTime function. This function has relatively poor resolution, between 1-16ms depending on the system, which is unacceptable for many real-world applications.
GetSystemTimePreciseAsFileTime on the other hand has a resolution between 1us and 100ns. This extra precision comes at a small performance cost[1], but it is still an extremely lightweight function call. I measured it at 20ns/call on my system. I believe GetSystemTimePreciseAsFileTime should be preferred whenever it is available (Windows Vista and higher)
There seems to be some FUD out there surrounding this function, however Microsoft recommends using this function in this fairly recent article [2] Quote:
See also: Same issue was identified and fixed a couple years ago in the .net runtime: [3]
[1] https://devblogs.microsoft.com/oldnewthing/20170921-00/?p=97057
[2] https://docs.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps.
[3] dotnet/coreclr#9736
The text was updated successfully, but these errors were encountered: