]> git.lizzy.rs Git - rust.git/blob - src/test/bench/shootout-pfib.rs
3ba6a6f7e2e92f4d02ecf5329e65ee8f974e38d9
[rust.git] / src / test / bench / shootout-pfib.rs
1 // -*- rust -*-
2 // xfail-pretty
3
4 /*
5   A parallel version of fibonacci numbers.
6
7   This version is meant mostly as a way of stressing and benchmarking
8   the task system. It supports a lot of command-line arguments to
9   control how it runs.
10
11 */
12
13 use std;
14
15 import vec;
16 import uint;
17 import std::time;
18 import str;
19 import int::range;
20 import std::io;
21 import std::getopts;
22 import task;
23 import u64;
24 import comm;
25 import comm::port;
26 import comm::chan;
27 import comm::send;
28 import comm::recv;
29
30 import core::result;
31 import result::{ok, err};
32
33 fn fib(n: int) -> int {
34     fn pfib(args: (chan<int>, int)) {
35         let (c, n) = args;
36         if n == 0 {
37             send(c, 0);
38         } else if n <= 2 {
39             send(c, 1);
40         } else {
41             let p = port();
42
43             let t1 = task::spawn((chan(p), n - 1), pfib);
44             let t2 = task::spawn((chan(p), n - 2), pfib);
45
46             send(c, recv(p) + recv(p));
47         }
48     }
49
50     let p = port();
51     let t = task::spawn((chan(p), n), pfib);
52     ret recv(p);
53 }
54
55 type config = {stress: bool};
56
57 fn parse_opts(argv: [str]) -> config {
58     let opts = [getopts::optflag("stress")];
59
60     let opt_args = vec::slice(argv, 1u, vec::len(argv));
61
62
63     alt getopts::getopts(opt_args, opts) {
64       ok(m) { ret {stress: getopts::opt_present(m, "stress")} }
65       err(_) { fail; }
66     }
67 }
68
69 fn stress_task(&&id: int) {
70     let i = 0;
71     while true {
72         let n = 15;
73         assert (fib(n) == fib(n));
74         i += 1;
75         #error("%d: Completed %d iterations", id, i);
76     }
77 }
78
79 fn stress(num_tasks: int) {
80     let tasks = [];
81     range(0, num_tasks) {|i|
82         tasks += [task::spawn_joinable(copy i, stress_task)];
83     }
84     for t in tasks { task::join(t); }
85 }
86
87 fn main(argv: [str]) {
88     if vec::len(argv) == 1u {
89         assert (fib(8) == 21);
90         log(debug, fib(8));
91     } else {
92         // Interactive mode! Wooo!!!!
93         let opts = parse_opts(argv);
94
95
96         if opts.stress {
97             stress(2);
98         } else {
99             let max = uint::parse_buf(str::bytes(argv[1]), 10u) as int;
100
101             let num_trials = 10;
102
103             let out = io::stdout();
104
105             range(1, max + 1) {|n|
106                 range(0, num_trials) {|i|
107                     let start = time::precise_time_ns();
108                     let fibn = fib(n);
109                     let stop = time::precise_time_ns();
110
111                     let elapsed = stop - start;
112
113                     out.write_line(#fmt["%d\t%d\t%s", n, fibn,
114                                         u64::str(elapsed)]);
115                 }
116             }
117         }
118     }
119 }