From cbc10fd3114374d394200d71b6f78204d891c0ba Mon Sep 17 00:00:00 2001 From: edef Date: Thu, 16 Apr 2015 05:50:54 -0400 Subject: [PATCH] cache page_size page_size is used in every nearly every pointer calculation in os.rs, and the Stack methods are called fairly often. It's definitely not worth spilling registers for to call out to a libc function. With this change, page_size becomes effectively free. It is cached in an atomic usize, with relaxed ordering, so no actual atomic operations are involved. Benchmark: ``` test bench_page_size ... bench: 5 ns/iter (+/- 1) test bench_page_size_cached ... bench: 0 ns/iter (+/- 0) ``` --- src/sys/mod.rs | 17 ++++++++++++++++- src/sys/unix.rs | 5 ++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 34f3dcb..7c2b1c2 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -1,5 +1,20 @@ -pub use self::imp::*; +use core::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; + +pub use self::imp::{map_stack, protect_stack, unmap_stack}; +use self::imp::sys_page_size; #[cfg(unix)] #[path = "unix.rs"] mod imp; + +static PAGE_SIZE_CACHE: AtomicUsize = ATOMIC_USIZE_INIT; +pub fn page_size() -> usize { + match PAGE_SIZE_CACHE.load(Ordering::Relaxed) { + 0 => { + let page_size = sys_page_size(); + PAGE_SIZE_CACHE.store(page_size, Ordering::Relaxed); + page_size + } + page_size => page_size + } +} diff --git a/src/sys/unix.rs b/src/sys/unix.rs index 284b427..e292633 100644 --- a/src/sys/unix.rs +++ b/src/sys/unix.rs @@ -3,10 +3,13 @@ use core::prelude::*; use self::libc::{c_void, c_int, size_t}; use self::libc::{mmap, mprotect, munmap}; use self::libc::MAP_FAILED; +use super::page_size; use core::ptr; -pub fn page_size() -> usize { +#[cold] +#[inline(never)] +pub fn sys_page_size() -> usize { unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }