Skip to content

black_box(f()) in scope 'b gets optimized away, unless fis ||:'a -> T and 'a > 'b #14367

Closed
@japaric

Description

@japaric

Script to reproduce:

extern crate test;
extern crate time;

use test::black_box;
use time::precise_time_ns;

fn fib(n: uint) -> uint {
    match n {
        0 | 1 => 1,
        n => fib(n - 1) + fib(n - 2),
    }
}

fn bench(fun: || -> uint) -> f64 {
    // KILL_SWITCH
    //let fun = || fib(20);

    let iters = 1_000;
    let start = precise_time_ns();
    for _ in range(0, iters) {
        black_box(fun());
    }
    let end = precise_time_ns();

    (end - start) as f64 / iters as f64
}

fn main() {
    println!("{}", bench(|| fib(20)))
}
$ rustc -O bench.rs && ./bench  # any `--opt-level` can be used instead of `-O`
31190.276
$ rustc -O bench.rs && ./bench  # change `iters` to `10_000`, output doesn't change too much as expected
30723.2899
$ rustc -O bench.rs && ./bench  # toggle KILL_SWITCH
4.0624
$ rustc -O bench.rs && ./bench  # change `iters` back to `1_000`
45.602
$ rustc --version
rustc 0.11.0-pre (e7e5e9c 2014-05-22 02:51:21 -0700)

I found this issue because I tried to benchmark directly in main without the auxiliar bench function, by calling black_box(fib(20)) in a loop, but black_box got optimized away and I got results like shown above.

My hypothesis is that black_box only seems to only work with closures whose captured env outlive the scope where black_box is used. The above example supports this hypothesis.

This issue doesn't (seem to) affect the Bencher framework right now. ButIi/when we get unboxed closures, the example above would pass an unboxed closure that captures nothing (a unit-like struct?), would black_box still work in that case?

cc @huonw

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions