Change:
The of uses a 64 bit multiplication that will overflow frequently. Using floats would be the easy way out, but it would reduce precision to 53 bits.
As a datapoint, this is literally what . Where is a . But we're multiplying by an extra 1000.
In fairness to Microsoft, they're operating on a time difference computed mod 2^64, so as long as the interval length is reasonable (less than a few thousand hours for a typical tick rate) it can't overflow. But computes an absolute time rather than a difference, so overflows are guaranteed to happen at some point. The 1000x factor only makes it more noticeable.
Since we're dealing with absolute time (and therefore something large), it's probably not unreasonable to divide first, or maybe even partially multiply by . Something like: maybe? What are "typical" and "extreme" tick rates and absolute ticks like? An incredibly robust implementation could presumably branch on the size of ticks to determine the optimal split of the .
The x86_64 architecture has the 64 bit MUL instruction whose result is effectively a 128 bit integer which never overflows. Likewise, the DIV instruction takes an effectively 128 bit integer as the dividened. i386 offers (u32, u32) -u64 MUL and (u64, u32) -(u32, u32) DIV/MOD, so we should be able to implement 64 bit MUL and DIV without overflow. Windows RT runs on ARMv7 (=~ Cortex-A). It has (u32, u32) -u64 UMULL but lacks DIV and we have to call a division routine. Perhaps we can forget about it for now...
We could use techniques similar to . Of course, in this case, we also have the multiplier, which together with the "magic constant" is going to overflow even a 128 bit register, but multiplication can be done "in parts".
Don't OSX and iOS have a similar problem and ? What is the typical value of seems to suggest that is can be large, just like on Windows.
^

Discussion:
use time::Duration; use sync::{Once, ONCE_INIT}; <ins> const NANOS_PER_SEC: i64 = 1_000_000_000; </ins> pub struct SteadyTime { t: libc::LARGE_INTEGER, }

} pub fn ns(&self) -> u64 { <del> self.t as u64 * 1_000_000_000 / frequency() as u64 </del> <ins> mul_div_i64(self.t as i64, NANOS_PER_SEC, frequency() as i64) as u64 </ins> } }

fn sub(self, other: &SteadyTime) -> Duration { let diff = self.t as i64 - other.t as i64; <del> Duration::microseconds(diff * 1_000_000 / frequency() as i64) </del> <ins> Duration::nanoseconds(mul_div_i64(diff, NANOS_PER_SEC, frequency() as i64)) </ins> } } <ins> // Computes (value*numer)/denom without overflow, as long as both // (numer*denom) and the overall result fit into i64 (which is the case // for our time conversions). fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 { let q = value / denom; let r = value % denom; // Decompose value as (value/denom*denom + value%denom), // substitute into (value*numer)/denom and simplify. // r < denom, so (denom*numer) is the upper bound of (r*numer) q * numer + r * numer / denom } #[test] fn test_muldiv() { assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000),  1_000_000_000_001_000); assert_eq!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000), -1_000_000_000_001_000); assert_eq!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000),  1_000_000_000_001_000); assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000), -1_000_000_000_001_000); assert_eq!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000),  1_000_000_000_001_000); } </ins>