pi/
pi.rs

1use may::go;
2use may::sync::mpsc;
3use may_actor::Actor;
4
5const TOTAL_NUM: usize = 100_000_000;
6const WORK_LOAD: usize = 10000;
7const ACTOR_NUMBER: usize = 100;
8
9#[inline]
10fn pow_of_minus_one(pow: usize) -> f64 {
11    if pow & 1 != 0 {
12        -1.0
13    } else {
14        1.0
15    }
16}
17
18#[inline]
19fn calc_work(start: usize, end: usize) -> f64 {
20    let mut sum = 0.0;
21    let mut divisor = 2 * start + 1;
22    for i in start..end {
23        sum += pow_of_minus_one(i) / divisor as f64;
24        divisor += 2;
25    }
26    sum
27}
28
29// single thread version for pi
30fn pi() -> f64 {
31    calc_work(0, TOTAL_NUM) * 4.0
32}
33
34// coroutine version for pi
35fn pi_coroutine() -> f64 {
36    let works = TOTAL_NUM / WORK_LOAD;
37    let (tx, rx) = mpsc::channel();
38
39    let mut start = 0;
40    for _ in 0..works {
41        let tx = tx.clone();
42        let end = start + WORK_LOAD;
43        go!(move || tx.send(calc_work(start, end)).unwrap());
44        start = end;
45    }
46
47    let mut sum = 0.0;
48    for _ in 0..works {
49        sum += rx.recv().unwrap();
50    }
51    sum * 4.0
52}
53
54// actor version for pi
55fn pi_actor() -> f64 {
56    const WORKS: usize = TOTAL_NUM / WORK_LOAD;
57
58    struct Worker;
59    impl Worker {
60        fn work(&self, master: Actor<Master>, start: usize, end: usize) {
61            let data = calc_work(start, end);
62            master.call(move |me| me.recv_data(data));
63        }
64    }
65
66    struct Master {
67        pi: f64,
68        count: usize,
69        tx: mpsc::Sender<f64>,
70    }
71
72    impl Master {
73        fn start(&self) {
74            // create the worker actors
75            let mut workers = Vec::with_capacity(ACTOR_NUMBER);
76            for _ in 0..ACTOR_NUMBER {
77                workers.push(Actor::new(Worker));
78            }
79
80            // send work load to workers
81            let mut start = 0;
82            for i in 0..WORKS {
83                let end = start + WORK_LOAD;
84                let master = unsafe { Actor::from(self) };
85                workers[i % ACTOR_NUMBER].call(move |me| me.work(master, start, end));
86                start = end;
87            }
88        }
89
90        fn recv_data(&mut self, data: f64) {
91            self.pi += data;
92            self.count += 1;
93            if self.count == WORKS {
94                self.tx.send(self.pi).unwrap();
95            }
96        }
97    }
98
99    let (tx, rx) = mpsc::channel();
100
101    // create the master actor
102    let master = Actor::new(Master {
103        pi: 0.0,
104        count: 0,
105        tx: tx,
106    });
107
108    master.call(|me| me.start());
109
110    rx.recv().unwrap() * 4.0
111}
112
113fn main() {
114    may::config().set_workers(4);
115    let dur = std::time::Instant::now();
116    println!("pi is {}, dur = {:?}", pi(), dur.elapsed());
117    let dur = std::time::Instant::now();
118    println!("pi is {}, dur = {:?}", pi_coroutine(), dur.elapsed());
119    let dur = std::time::Instant::now();
120    println!("pi is {}, dur = {:?}", pi_actor(), dur.elapsed());
121}