Skip to content

Commit

Permalink
Optimize common path of Once::doit
Browse files Browse the repository at this point in the history
Optimize `Once::doit`: perform optimistic check that initializtion is
already completed.  `load` is much cheaper than `fetch_add` at least
on x86_64.

Verified with this test:

```
static mut o: one::Once = one::ONCE_INIT;
unsafe {
    loop {
        let start = time::precise_time_ns();
        let iters = 50000000u64;
        for _ in range(0, iters) {
            o.doit(|| { println!("once!"); });
        }
        let end = time::precise_time_ns();
        let ps_per_iter = 1000 * (end - start) / iters;
        println!("{} ps per iter", ps_per_iter);

        // confuse the optimizer
        o.doit(|| { println!("once!"); });
    }
}
```

Test executed on Mac, Intel Core i7 2GHz. Result is:
* 20ns per iteration without patch
*  4ns per iteration with this patch applied

Once.doit could be even faster (800ps per iteration), if `doit` function
was split into a pair of `doit`/`doit_slow`, and `doit` marked as
`#[inline]` like this:

```
#[inline(always)]
pub fn doit(&self, f: ||) {
    if self.cnt.load(atomics::SeqCst) < 0 {
        return
    }

    self.doit_slow(f);
}

fn doit_slow(&self, f: ||) { ... }
```
  • Loading branch information
stepancheg committed May 14, 2014
1 parent db5ca23 commit f853cf7
Showing 1 changed file with 5 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/libsync/one.rs
Expand Up @@ -64,6 +64,11 @@ impl Once {
/// When this function returns, it is guaranteed that some initialization
/// has run and completed (it may not be the closure specified).
pub fn doit(&self, f: ||) {
// Optimize common path: load is much cheaper than fetch_add.
if self.cnt.load(atomics::SeqCst) < 0 {
return
}

// Implementation-wise, this would seem like a fairly trivial primitive.
// The stickler part is where our mutexes currently require an
// allocation, and usage of a `Once` should't leak this allocation.
Expand Down

5 comments on commit f853cf7

@bors
Copy link
Contributor

@bors bors commented on f853cf7 May 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at stepancheg@f853cf7

@bors
Copy link
Contributor

@bors bors commented on f853cf7 May 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging stepancheg/rust/once = f853cf7 into auto

@bors
Copy link
Contributor

@bors bors commented on f853cf7 May 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stepancheg/rust/once = f853cf7 merged ok, testing candidate = f2c4c88

@bors
Copy link
Contributor

@bors bors commented on f853cf7 May 15, 2014

@bors
Copy link
Contributor

@bors bors commented on f853cf7 May 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = f2c4c88

Please sign in to comment.