1 use super::{Duration, Instant, SystemTime, UNIX_EPOCH};
2 #[cfg(not(target_arch = "wasm32"))]
3 use test::{black_box, Bencher};
5 macro_rules! assert_almost_eq {
6 ($a:expr, $b:expr) => {{
9 let (a, b) = if a > b { (a, b) } else { (b, a) };
10 assert!(a - Duration::from_micros(1) <= b, "{:?} is not almost equal to {:?}", a, b);
16 fn instant_monotonic() {
17 let a = Instant::now();
19 let b = Instant::now();
28 #[cfg(not(target_arch = "wasm32"))]
29 fn instant_monotonic_concurrent() -> crate::thread::Result<()> {
30 let threads: Vec<_> = (0..8)
32 crate::thread::spawn(|| {
33 let mut old = Instant::now();
34 let count = if cfg!(miri) { 1_000 } else { 5_000_000 };
36 let new = Instant::now();
50 fn instant_elapsed() {
51 let a = Instant::now();
57 let a = Instant::now();
58 let b = Instant::now();
61 let dur = b.duration_since(a);
62 println!("dur: {dur:?}");
63 assert_almost_eq!(b - dur, a);
64 assert_almost_eq!(a + dur, b);
66 let second = Duration::SECOND;
67 assert_almost_eq!(a - second + second, a);
68 assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
70 // checked_add_duration will not panic on overflow
71 let mut maybe_t = Some(Instant::now());
72 let max_duration = Duration::from_secs(u64::MAX);
73 // in case `Instant` can store `>= now + max_duration`.
75 maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
77 assert_eq!(maybe_t, None);
79 // checked_add_duration calculates the right time and will work for another year
80 let year = Duration::from_secs(60 * 60 * 24 * 365);
81 assert_eq!(a + year, a.checked_add(year).unwrap());
85 fn instant_math_is_associative() {
86 let now = Instant::now();
87 let offset = Duration::from_millis(5);
88 // Changing the order of instant math shouldn't change the results,
89 // especially when the expression reduces to X + identity.
90 assert_eq!((now + offset) - now, (now - now) + offset);
92 // On any platform, `Instant` should have the same resolution as `Duration` (e.g. 1 nanosecond)
93 // or better. Otherwise, math will be non-associative (see #91417).
94 let now = Instant::now();
95 let provided_offset = Duration::from_nanos(1);
96 let later = now + provided_offset;
97 let measured_offset = later - now;
98 assert_eq!(measured_offset, provided_offset);
102 fn instant_duration_since_saturates() {
103 let a = Instant::now();
104 assert_eq!((a - Duration::SECOND).duration_since(a), Duration::ZERO);
108 fn instant_checked_duration_since_nopanic() {
109 let now = Instant::now();
110 let earlier = now - Duration::SECOND;
111 let later = now + Duration::SECOND;
112 assert_eq!(earlier.checked_duration_since(now), None);
113 assert_eq!(later.checked_duration_since(now), Some(Duration::SECOND));
114 assert_eq!(now.checked_duration_since(now), Some(Duration::ZERO));
118 fn instant_saturating_duration_since_nopanic() {
119 let a = Instant::now();
120 #[allow(deprecated, deprecated_in_future)]
121 let ret = (a - Duration::SECOND).saturating_duration_since(a);
122 assert_eq!(ret, Duration::ZERO);
126 fn system_time_math() {
127 let a = SystemTime::now();
128 let b = SystemTime::now();
129 match b.duration_since(a) {
130 Ok(Duration::ZERO) => {
131 assert_almost_eq!(a, b);
135 assert_almost_eq!(b - dur, a);
136 assert_almost_eq!(a + dur, b);
139 let dur = dur.duration();
141 assert_almost_eq!(b + dur, a);
142 assert_almost_eq!(a - dur, b);
146 let second = Duration::SECOND;
147 assert_almost_eq!(a.duration_since(a - second).unwrap(), second);
148 assert_almost_eq!(a.duration_since(a + second).unwrap_err().duration(), second);
150 assert_almost_eq!(a - second + second, a);
151 assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
153 let one_second_from_epoch = UNIX_EPOCH + Duration::SECOND;
154 let one_second_from_epoch2 =
155 UNIX_EPOCH + Duration::from_millis(500) + Duration::from_millis(500);
156 assert_eq!(one_second_from_epoch, one_second_from_epoch2);
158 // checked_add_duration will not panic on overflow
159 let mut maybe_t = Some(SystemTime::UNIX_EPOCH);
160 let max_duration = Duration::from_secs(u64::MAX);
161 // in case `SystemTime` can store `>= UNIX_EPOCH + max_duration`.
163 maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
165 assert_eq!(maybe_t, None);
167 // checked_add_duration calculates the right time and will work for another year
168 let year = Duration::from_secs(60 * 60 * 24 * 365);
169 assert_eq!(a + year, a.checked_add(year).unwrap());
173 fn system_time_elapsed() {
174 let a = SystemTime::now();
180 let ts = SystemTime::now();
181 let a = ts.duration_since(UNIX_EPOCH + Duration::SECOND).unwrap();
182 let b = ts.duration_since(UNIX_EPOCH).unwrap();
184 assert_eq!(b - a, Duration::SECOND);
186 let thirty_years = Duration::SECOND * 60 * 60 * 24 * 365 * 30;
188 // Right now for CI this test is run in an emulator, and apparently the
189 // aarch64 emulator's sense of time is that we're still living in the
190 // 70s. This is also true for riscv (also qemu)
192 // Otherwise let's assume that we're all running computers later than
194 if !cfg!(target_arch = "aarch64") && !cfg!(target_arch = "riscv64") {
195 assert!(a > thirty_years);
198 // let's assume that we're all running computers earlier than 2090.
199 // Should give us ~70 years to fix this!
200 let hundred_twenty_years = thirty_years * 4;
201 assert!(a < hundred_twenty_years);
204 macro_rules! bench_instant_threaded {
205 ($bench_name:ident, $thread_count:expr) => {
207 #[cfg(not(target_arch = "wasm32"))]
208 fn $bench_name(b: &mut Bencher) -> crate::thread::Result<()> {
209 use crate::sync::atomic::{AtomicBool, Ordering};
210 use crate::sync::Arc;
212 let running = Arc::new(AtomicBool::new(true));
214 let threads: Vec<_> = (0..$thread_count)
216 let flag = Arc::clone(&running);
217 crate::thread::spawn(move || {
218 while flag.load(Ordering::Relaxed) {
219 black_box(Instant::now());
226 let a = Instant::now();
227 let b = Instant::now();
231 running.store(false, Ordering::Relaxed);
241 bench_instant_threaded!(instant_contention_01_threads, 0);
242 bench_instant_threaded!(instant_contention_02_threads, 1);
243 bench_instant_threaded!(instant_contention_04_threads, 3);
244 bench_instant_threaded!(instant_contention_08_threads, 7);
245 bench_instant_threaded!(instant_contention_16_threads, 15);