about summary refs log tree commit diff
path: root/src/libtime
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-05-16 16:31:24 -0700
committerbors <bors@rust-lang.org>2014-05-16 16:31:24 -0700
commit2216eceea51b344560f4791336b3ea2c897eec39 (patch)
tree231d3f6640253dc2371426efe5ea67ff53b8d226 /src/libtime
parentcea4803d4cf56ded65be6a9e043a6219c661c572 (diff)
parent8ef3e227198f6ff674b1626d0862c4112358c1a1 (diff)
auto merge of #14216 : kballard/rust/macos_precise_time_ns, r=alexcrichton
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.
Diffstat (limited to 'src/libtime')
-rw-r--r--src/libtime/lib.rs23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs
index b580626c9c3..0e67076dc08 100644
--- a/src/libtime/lib.rs
+++ b/src/libtime/lib.rs
@@ -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 @@ pub fn 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 @@ pub fn strftime(format: &str, 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 @@ mod tests {
         test_strftime();
         test_timespec_eq_ord();
     }
+
+    #[bench]
+    fn bench_precise_time_ns(b: &mut Bencher) {
+        b.iter(|| precise_time_ns())
+    }
 }