]> git.lizzy.rs Git - rust.git/commitdiff
Optimize and fix time::precise_time_ns() on macos
authorKevin Ballard <kevin@sb.org>
Thu, 15 May 2014 00:54:36 +0000 (17:54 -0700)
committerKevin Ballard <kevin@sb.org>
Fri, 16 May 2014 21:02:14 +0000 (14:02 -0700)
Use sync::one::Once to fetch the mach_timebase_info only once when
running precise_time_ns(). This helps because mach_timebase_info() is
surprisingly inefficient. Also fix the order of operations when applying
the timebase to the mach absolute time value.

This improves the time on my machine from

```
test tests::bench_precise_time_ns ... bench:       157 ns/iter (+/- 4)
```

to

```
test tests::bench_precise_time_ns ... bench:        38 ns/iter (+/- 3)
```

and it will get even faster once #14174 lands.

mk/crates.mk
src/libtime/lib.rs

index 895819a5a50c0aae692a26c9e904a4155dac5908..4ac4abe9063ef9662855ec4b8d444cf9a3223b09 100644 (file)
@@ -83,7 +83,7 @@ DEPS_fourcc := syntax std
 DEPS_hexfloat := syntax std
 DEPS_num := std rand
 DEPS_test := std collections getopts serialize term time regex
-DEPS_time := std serialize
+DEPS_time := std serialize sync
 DEPS_rand := std
 DEPS_url := std collections
 DEPS_workcache := std serialize collections log
index 87a87641fc03b247587bcf64d6e4f030329cdd0b..812985dd199335b8b3ea0b0d795f48040a0e39e6 100644 (file)
@@ -24,6 +24,8 @@
 #[cfg(test)] #[phase(syntax, link)] extern crate log;
 extern crate serialize;
 extern crate libc;
+#[cfg(target_os = "macos")]
+extern crate sync;
 
 use std::io::BufReader;
 use std::num;
@@ -159,10 +161,16 @@ fn os_precise_time_ns() -> u64 {
 
     #[cfg(target_os = "macos")]
     fn os_precise_time_ns() -> u64 {
-        let time = unsafe { imp::mach_absolute_time() };
-        let mut info = libc::mach_timebase_info { numer: 0, denom: 0 };
-        unsafe { imp::mach_timebase_info(&mut info); }
-        return time * ((info.numer / info.denom) as u64);
+        static mut TIMEBASE: libc::mach_timebase_info = libc::mach_timebase_info { numer: 0,
+                                                                                   denom: 0 };
+        static mut ONCE: sync::one::Once = sync::one::ONCE_INIT;
+        unsafe {
+            ONCE.doit(|| {
+                imp::mach_timebase_info(&mut TIMEBASE);
+            });
+            let time = imp::mach_absolute_time();
+            time * TIMEBASE.numer as u64 / TIMEBASE.denom as u64
+        }
     }
 
     #[cfg(not(windows), not(target_os = "macos"))]
@@ -1080,11 +1088,13 @@ fn parse_type(ch: char, tm: &Tm) -> StrBuf {
 
 #[cfg(test)]
 mod tests {
+    extern crate test;
     use super::{Timespec, get_time, precise_time_ns, precise_time_s, tzset,
                 at_utc, at, strptime};
 
     use std::f64;
     use std::result::{Err, Ok};
+    use self::test::Bencher;
 
     #[cfg(windows)]
     fn set_time_zone() {
@@ -1520,4 +1530,9 @@ fn run_tests() {
         test_strftime();
         test_timespec_eq_ord();
     }
+
+    #[bench]
+    fn bench_precise_time_ns(b: &mut Bencher) {
+        b.iter(|| precise_time_ns())
+    }
 }