Skip to content

Commit 3557616

Browse files
committed
Added a benchmark of bounded vs unbounded. Bounded is 8-12% faster. The macros currently don't work without pretty printing first.
1 parent 7f5f1f9 commit 3557616

File tree

2 files changed

+161
-13
lines changed

2 files changed

+161
-13
lines changed

src/libcore/pipes.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,15 +273,15 @@ class buffer_resource<T: send> {
273273
let buffer: ~buffer<T>;
274274
new(+b: ~buffer<T>) {
275275
let p = ptr::addr_of(*b);
276-
#error("take %?", p);
276+
//#error("take %?", p);
277277
atomic_add_acq(b.header.ref_count, 1);
278278
self.buffer = b;
279279
}
280280

281281
drop unsafe {
282282
let b = move!{self.buffer};
283283
let p = ptr::addr_of(*b);
284-
#error("drop %?", p);
284+
//#error("drop %?", p);
285285
let old_count = atomic_sub_rel(b.header.ref_count, 1);
286286
//let old_count = atomic_xchng_rel(b.header.ref_count, 0);
287287
if old_count == 1 {
@@ -363,7 +363,7 @@ fn try_recv<T: send, Tbuffer: send>(-p: recv_packet_buffered<T, Tbuffer>)
363363
full {
364364
let mut payload = none;
365365
payload <-> p.payload;
366-
p.header.state = terminated;
366+
p.header.state = empty;
367367
ret some(option::unwrap(payload))
368368
}
369369
terminated {
@@ -560,10 +560,10 @@ class send_packet_buffered<T: send, Tbuffer: send> {
560560
p <-> self.p;
561561
sender_terminate(option::unwrap(p))
562562
}
563-
unsafe { #error("send_drop: %?",
564-
if self.buffer == none {
565-
"none"
566-
} else { "some" }); }
563+
//unsafe { #error("send_drop: %?",
564+
// if self.buffer == none {
565+
// "none"
566+
// } else { "some" }); }
567567
}
568568
fn unwrap() -> *packet<T> {
569569
let mut p = none;
@@ -586,7 +586,7 @@ class send_packet_buffered<T: send, Tbuffer: send> {
586586
}
587587

588588
fn reuse_buffer() -> buffer_resource<Tbuffer> {
589-
#error("send reuse_buffer");
589+
//#error("send reuse_buffer");
590590
let mut tmp = none;
591591
tmp <-> self.buffer;
592592
option::unwrap(tmp)
@@ -620,10 +620,10 @@ class recv_packet_buffered<T: send, Tbuffer: send> : selectable {
620620
p <-> self.p;
621621
receiver_terminate(option::unwrap(p))
622622
}
623-
unsafe { #error("recv_drop: %?",
624-
if self.buffer == none {
625-
"none"
626-
} else { "some" }); }
623+
//unsafe { #error("recv_drop: %?",
624+
// if self.buffer == none {
625+
// "none"
626+
// } else { "some" }); }
627627
}
628628
fn unwrap() -> *packet<T> {
629629
let mut p = none;
@@ -646,7 +646,7 @@ class recv_packet_buffered<T: send, Tbuffer: send> : selectable {
646646
}
647647

648648
fn reuse_buffer() -> buffer_resource<Tbuffer> {
649-
#error("recv reuse_buffer");
649+
//#error("recv reuse_buffer");
650650
let mut tmp = none;
651651
tmp <-> self.buffer;
652652
option::unwrap(tmp)

src/test/bench/pingpong.rs

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// Compare bounded and unbounded protocol performance.
2+
3+
// xfail-test
4+
// xfail-pretty
5+
6+
use std;
7+
8+
import pipes::{spawn_service, recv};
9+
import std::time::precise_time_s;
10+
11+
proto! pingpong {
12+
ping: send {
13+
ping -> pong
14+
}
15+
16+
pong: recv {
17+
pong -> ping
18+
}
19+
}
20+
21+
proto! pingpong_unbounded {
22+
ping: send {
23+
ping -> pong
24+
}
25+
26+
pong: recv {
27+
pong -> ping
28+
}
29+
30+
you_will_never_catch_me: send {
31+
never_ever_ever -> you_will_never_catch_me
32+
}
33+
}
34+
35+
// This stuff should go in libcore::pipes
36+
macro_rules! move {
37+
{ $x:expr } => { unsafe { let y <- *ptr::addr_of($x); y } }
38+
}
39+
40+
macro_rules! follow {
41+
{
42+
$($message:path($($x: ident),+) -> $next:ident $e:expr)+
43+
} => (
44+
|m| alt move(m) {
45+
$(some($message($($x,)* next)) {
46+
let $next = move!{next};
47+
$e })+
48+
_ { fail }
49+
}
50+
);
51+
52+
{
53+
$($message:path -> $next:ident $e:expr)+
54+
} => (
55+
|m| alt move(m) {
56+
$(some($message(next)) {
57+
let $next = move!{next};
58+
$e })+
59+
_ { fail }
60+
}
61+
)
62+
}
63+
64+
fn switch<T: send, Tb: send, U>(+endp: pipes::recv_packet_buffered<T, Tb>,
65+
f: fn(+option<T>) -> U) -> U {
66+
f(pipes::try_recv(endp))
67+
}
68+
69+
fn move<T>(-x: T) -> T { x }
70+
71+
// Here's the benchmark
72+
73+
fn bounded(count: uint) {
74+
import pingpong::*;
75+
76+
let mut ch = do spawn_service(init) |ch| {
77+
let mut count = count;
78+
let mut ch = ch;
79+
while count > 0 {
80+
ch = switch(ch, follow! {
81+
ping -> next { server::pong(next) }
82+
});
83+
84+
count -= 1;
85+
}
86+
};
87+
88+
let mut count = count;
89+
while count > 0 {
90+
let ch_ = client::ping(ch);
91+
92+
ch = switch(ch_, follow! {
93+
pong -> next { next }
94+
});
95+
96+
count -= 1;
97+
}
98+
}
99+
100+
fn unbounded(count: uint) {
101+
import pingpong_unbounded::*;
102+
103+
let mut ch = do spawn_service(init) |ch| {
104+
let mut count = count;
105+
let mut ch = ch;
106+
while count > 0 {
107+
ch = switch(ch, follow! {
108+
ping -> next { server::pong(next) }
109+
});
110+
111+
count -= 1;
112+
}
113+
};
114+
115+
let mut count = count;
116+
while count > 0 {
117+
let ch_ = client::ping(ch);
118+
119+
ch = switch(ch_, follow! {
120+
pong -> next { next }
121+
});
122+
123+
count -= 1;
124+
}
125+
}
126+
127+
fn timeit(f: fn()) -> float {
128+
let start = precise_time_s();
129+
f();
130+
let stop = precise_time_s();
131+
stop - start
132+
}
133+
134+
fn main() {
135+
let count = 1000000;
136+
let bounded = do timeit { bounded(count) };
137+
let unbounded = do timeit { unbounded(count) };
138+
139+
io::println(#fmt("count: %?\n", count));
140+
io::println(#fmt("bounded: %? s\t(%? μs/message)",
141+
bounded, bounded * 1000000. / (count as float)));
142+
io::println(#fmt("unbounded: %? s\t(%? μs/message)",
143+
unbounded, unbounded * 1000000. / (count as float)));
144+
145+
io::println(#fmt("\n\
146+
bounded is %?%% faster",
147+
(unbounded - bounded) / bounded * 100.));
148+
}

0 commit comments

Comments
 (0)