performance measurements

Each table row shows performance measurements for this Rust program with a particular command-line input value N.

 N  CPU secs Elapsed secs Memory KB Code B ≈ CPU Load
100.300.313521180  0% 6% 0% 100%
113.643.646,9081180  1% 1% 1% 100%
1248.6248.646,9161180  1% 1% 0% 100%

Read the ↓ make, command line, and program output logs to see how this program was run.

Read fannkuch-redux benchmark to see what this program should do.

 notes

rustc 0.12.0 (ba4081a5a 2014-10-07 13:44:41 -0700)

 fannkuch-redux Rust #2 program source code

// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers
// contributed by TeXitoi

#![feature(slicing_syntax)]

use std::{cmp, iter, mem};
use std::sync::Future;

fn rotate(x: &mut [i32]) {
    let mut prev = x[0];
    for place in x.iter_mut().rev() {
        prev = mem::replace(place, prev)
    }
}

fn next_permutation(perm: &mut [i32], count: &mut [i32]) {
    for i in range(1, perm.len()) {
        rotate(perm[mut ..i + 1]);
        let count_i = &mut count[i];
        if *count_i >= i as i32 {
            *count_i = 0;
        } else {
            *count_i += 1;
            break
        }
    }
}

struct P {
    p: [i32, .. 16],
}

struct Perm {
    cnt: [i32, .. 16],
    fact: [u32, .. 16],
    n: u32,
    permcount: u32,
    perm: P,
}

impl Perm {
    fn new(n: u32) -> Perm {
        let mut fact = [1, .. 16];
        for i in range(1, n as uint + 1) {
            fact[i] = fact[i - 1] * i as u32;
        }
        Perm {
            cnt: [0, .. 16],
            fact: fact,
            n: n,
            permcount: 0,
            perm: P { p: [0, .. 16 ] }
        }
    }

    fn get(&mut self, mut idx: i32) -> P {
        let mut pp = [0u8, .. 16];
        self.permcount = idx as u32;
        for (i, place) in self.perm.p.iter_mut().enumerate() {
            *place = i as i32 + 1;
        }

        for i in range(1, self.n as uint).rev() {
            let d = idx / self.fact[i] as i32;
            self.cnt[i] = d;
            idx %= self.fact[i] as i32;
            for (place, val) in pp.iter_mut().zip(self.perm.p[..i+1].iter()) {
                *place = (*val) as u8
            }

            let d = d as uint;
            for j in range(0, i + 1) {
                self.perm.p[j] = if j + d <= i {pp[j + d]} else {pp[j+d-i-1]} as i32;
            }
        }

        self.perm
    }

    fn count(&self) -> u32 { self.permcount }
    fn max(&self) -> u32 { self.fact[self.n as uint] }

    fn next(&mut self) -> P {
        next_permutation(self.perm.p, self.cnt);
        self.permcount += 1;

        self.perm
    }
}


fn reverse(tperm: &mut [i32], mut k: uint) {
    tperm[mut ..k].reverse()
}

fn work(mut perm: Perm, n: uint, max: uint) -> (i32, i32) {
    let mut checksum = 0;
    let mut maxflips = 0;

    let mut p = perm.get(n as i32);

    while perm.count() < max as u32 {
        let mut flips = 0;

        while p.p[0] != 1 {
            let k = p.p[0] as uint;
            reverse(p.p, k);
            flips += 1;
        }

        checksum += if perm.count() % 2 == 0 {flips} else {-flips};
        maxflips = cmp::max(maxflips, flips);

        p = perm.next();
    }

    (checksum, maxflips)
}

fn fannkuch(n: i32) -> (i32, i32) {
    let perm = Perm::new(n as u32);

    let N = 4;
    let mut futures = vec![];
    let k = perm.max() / N;

    for (i, j) in range(0, N).zip(iter::count(0, k)) {
        let max = cmp::min(j+k, perm.max());

        futures.push(Future::spawn(proc() {
            work(perm, j as uint, max as uint)
        }))
    }

    let mut checksum = 0;
    let mut maxflips = 0;
    for fut in futures.iter_mut() {
        let (cs, mf) = fut.get();
        checksum += cs;
        maxflips = cmp::max(maxflips, mf);
    }
    (checksum, maxflips)
}

fn main() {
    let n = std::os::args().as_slice()
        .get(1)
        .and_then(|arg| from_str(arg.as_slice()))
        .unwrap_or(2i32);

    let (checksum, maxflips) = fannkuch(n);
    println!("{}\nPfannkuchen({}) = {}", checksum, n, maxflips);
}

 make, command-line, and program output logs

Mon, 13 Oct 2014 00:24:45 GMT

MAKE:
/usr/local/src/rust/bin/rustc --opt-level=3 -C target-cpu=core2 -C lto fannkuchredux.rs -o fannkuchredux.rust-2.rust_run
fannkuchredux.rs:95:31: 95:36 warning: variable does not need to be mutable, #[warn(unused_mut)] on by default
fannkuchredux.rs:95 fn reverse(tperm: &mut [i32], mut k: uint) {
                                                  ^~~~~
fannkuchredux.rs:130:10: 130:11 warning: unused variable: `i`, #[warn(unused_variable)] on by default
fannkuchredux.rs:130     for (i, j) in range(0, N).zip(iter::count(0, k)) {
                              ^
fannkuchredux.rs:126:9: 126:10 warning: variable `N` should have a snake case name such as `n`, #[warn(non_snake_case)] on by default
fannkuchredux.rs:126     let N = 4;
                             ^
16.33s to complete and log all make actions

COMMAND LINE:
./fannkuchredux.rust-2.rust_run 12

PROGRAM OUTPUT:
3968050
Pfannkuchen(12) = 65

Revised BSD license

  Home   Conclusions   License   Play