Skip to content

Commit 77f721a

Browse files
author
Eric Holk
committed
---
yaml --- r: 4089 b: refs/heads/master c: 8878b12 h: refs/heads/master i: 4087: 1c69234 v: v3
1 parent 4f3ed54 commit 77f721a

File tree

7 files changed

+135
-37
lines changed

7 files changed

+135
-37
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 8f2254b8c28c17bf7346975205b623ee92ba947c
2+
refs/heads/master: 8878b128baddfa4ee38e4f9c43be75abe0edcd3d

trunk/src/lib/task.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ native "rust" mod rustrt {
55
fn unsupervise();
66
fn pin_task();
77
fn unpin_task();
8+
fn clone_chan(*rust_chan c) -> *rust_chan;
9+
10+
type rust_chan;
811
}
912

1013
/**
@@ -44,6 +47,11 @@ fn unpin() {
4447
rustrt::unpin_task();
4548
}
4649

50+
fn clone_chan[T](chan[T] c) -> chan[T] {
51+
auto cloned = rustrt::clone_chan(unsafe::reinterpret_cast(c));
52+
ret unsafe::reinterpret_cast(cloned);
53+
}
54+
4755
// Local Variables:
4856
// mode: rust;
4957
// fill-column: 78;

trunk/src/rt/rust_builtin.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,11 @@ unpin_task(rust_task *task) {
850850
task->unpin();
851851
}
852852

853+
extern "C" CDECL rust_chan *
854+
clone_chan(rust_task *task, rust_chan *chan) {
855+
return chan->clone(task);
856+
}
857+
853858
//
854859
// Local Variables:
855860
// mode: C++

trunk/src/rt/rust_chan.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,16 @@ void rust_chan::disassociate() {
7171
* Attempt to send data to the associated port.
7272
*/
7373
void rust_chan::send(void *sptr) {
74+
rust_scheduler *sched = kernel->sched;
75+
I(sched, !port->is_proxy());
76+
77+
rust_port *target_port = port->referent();
78+
// TODO: We can probably avoid this lock by using atomic operations in
79+
// circular_buffer.
80+
scoped_lock with(target_port->lock);
81+
7482
buffer.enqueue(sptr);
7583

76-
rust_scheduler *sched = kernel->sched;
7784
if (!is_associated()) {
7885
W(sched, is_associated(),
7986
"rust_chan::transmit with no associated port.");
@@ -88,8 +95,6 @@ void rust_chan::send(void *sptr) {
8895
task->get_handle(), port->as_proxy()->handle());
8996
buffer.dequeue(NULL);
9097
} else {
91-
rust_port *target_port = port->referent();
92-
scoped_lock with(target_port->lock);
9398
if (target_port->task->blocked_on(target_port)) {
9499
DLOG(sched, comm, "dequeued in rendezvous_ptr");
95100
buffer.dequeue(target_port->task->rendezvous_ptr);

trunk/src/rt/rustrt.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
align_of
22
check_claims
3+
clone_chan
34
debug_box
45
debug_fn
56
debug_obj

trunk/src/test/bench/task-perf/word-count.rs

Lines changed: 110 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,49 @@ import std::option::none;
1717
import std::str;
1818
import std::vec;
1919
import std::map;
20+
import std::ivec;
21+
22+
import std::time;
23+
import std::u64;
24+
25+
import std::task;
26+
import clone = std::task::clone_chan;
2027

2128
fn map(str filename, map_reduce::putter emit) {
29+
// log_err "mapping " + filename;
2230
auto f = io::file_reader(filename);
2331

2432
while(true) {
2533
alt(read_word(f)) {
2634
case (some(?w)) {
27-
emit(w, "1");
35+
emit(w, 1);
2836
}
2937
case (none) {
3038
break;
3139
}
3240
}
3341
}
42+
// log_err "done mapping " + filename;
3443
}
3544

3645
fn reduce(str word, map_reduce::getter get) {
46+
// log_err "reducing " + word;
3747
auto count = 0;
3848

3949
while(true) {
4050
alt(get()) {
41-
case(some(_)) { count += 1 }
42-
case(none) { break }
51+
some(_) {
52+
// log_err "received word " + word;
53+
count += 1;
54+
}
55+
none { break }
4356
}
4457
}
4558

46-
auto out = io::stdout();
47-
out.write_line(#fmt("%s: %d", word, count));
59+
// auto out = io::stdout();
60+
// out.write_line(#fmt("%s: %d", word, count));
61+
62+
// log_err "reduce " + word + " done.";
4863
}
4964

5065
mod map_reduce {
@@ -54,74 +69,115 @@ mod map_reduce {
5469
export reducer;
5570
export map_reduce;
5671

57-
type putter = fn(str, str) -> ();
72+
type putter = fn(str, int) -> ();
5873

5974
type mapper = fn(str, putter);
6075

61-
type getter = fn() -> option[str];
76+
type getter = fn() -> option[int];
6277

6378
type reducer = fn(str, getter);
6479

6580
tag ctrl_proto {
66-
find_reducer(str, chan[chan[reduce_proto]]);
81+
find_reducer(u8[], chan[chan[reduce_proto]]);
6782
mapper_done;
6883
}
6984

7085
tag reduce_proto {
71-
emit_val(str);
86+
emit_val(int);
7287
done;
88+
ref;
89+
release;
7390
}
7491

7592
fn start_mappers(chan[ctrl_proto] ctrl,
76-
vec[str] inputs) {
93+
vec[str] inputs) -> task[] {
94+
auto tasks = ~[];
95+
// log_err "starting mappers";
7796
for(str i in inputs) {
78-
spawn map_task(ctrl, i);
97+
// log_err "starting mapper for " + i;
98+
tasks += ~[spawn map_task(ctrl, i)];
7999
}
100+
// log_err "done starting mappers";
101+
ret tasks;
80102
}
81103

82104
fn map_task(chan[ctrl_proto] ctrl,
83105
str input) {
84-
106+
// log_err "map_task " + input;
85107
auto intermediates = map::new_str_hash();
86108

87109
fn emit(&map::hashmap[str, chan[reduce_proto]] im,
88110
chan[ctrl_proto] ctrl,
89-
str key, str val) {
111+
str key, int val) {
112+
// log_err "emitting " + key;
90113
auto c;
91114
alt(im.find(key)) {
92-
case(some(?_c)) {
115+
some(?_c) {
116+
// log_err "reusing saved channel for " + key;
93117
c = _c
94118
}
95-
case(none) {
119+
none {
120+
// log_err "fetching new channel for " + key;
96121
auto p = port[chan[reduce_proto]]();
97-
ctrl <| find_reducer(key, chan(p));
122+
auto keyi = str::bytes_ivec(key);
123+
ctrl <| find_reducer(keyi, chan(p));
98124
p |> c;
99-
im.insert(key, c);
125+
im.insert(key, clone(c));
126+
c <| ref;
100127
}
101128
}
102129
c <| emit_val(val);
103130
}
104131

105132
map(input, bind emit(intermediates, ctrl, _, _));
133+
134+
for each(@tup(str, chan[reduce_proto]) kv in intermediates.items()) {
135+
// log_err "sending done to reducer for " + kv._0;
136+
kv._1 <| release;
137+
}
138+
106139
ctrl <| mapper_done;
140+
141+
// log_err "~map_task " + input;
107142
}
108143

109144
fn reduce_task(str key, chan[chan[reduce_proto]] out) {
145+
// log_err "reduce_task " + key;
110146
auto p = port();
111147

112148
out <| chan(p);
113149

114-
fn get(port[reduce_proto] p) -> option[str] {
115-
auto m;
116-
p |> m;
150+
auto ref_count = 0;
151+
auto is_done = false;
117152

118-
alt(m) {
119-
case(emit_val(?v)) { ret some(v); }
120-
case(done) { ret none; }
153+
fn get(&port[reduce_proto] p, &mutable int ref_count,
154+
&mutable bool is_done) -> option[int] {
155+
while (!is_done || ref_count > 0) {
156+
auto m;
157+
p |> m;
158+
159+
alt(m) {
160+
emit_val(?v) {
161+
// log_err #fmt("received %d", v);
162+
ret some(v);
163+
}
164+
done {
165+
// log_err "all done";
166+
is_done = true;
167+
}
168+
ref {
169+
ref_count += 1;
170+
}
171+
release {
172+
ref_count -= 1;
173+
}
174+
}
121175
}
176+
ret none;
122177
}
123178

124-
reduce(key, bind get(p));
179+
reduce(key, bind get(p, ref_count, is_done));
180+
// log_err "~reduce_task " + key;
125181
}
126182

127183
fn map_reduce (vec[str] inputs) {
@@ -134,7 +190,7 @@ mod map_reduce {
134190

135191
reducers = map::new_str_hash();
136192

137-
start_mappers(chan(ctrl), inputs);
193+
auto tasks = start_mappers(chan(ctrl), inputs);
138194

139195
auto num_mappers = vec::len(inputs) as int;
140196

@@ -143,26 +199,42 @@ mod map_reduce {
143199
ctrl |> m;
144200

145201
alt(m) {
146-
case(mapper_done) { num_mappers -= 1; }
147-
case(find_reducer(?k, ?cc)) {
202+
mapper_done {
203+
// log_err "received mapper terminated.";
204+
num_mappers -= 1;
205+
}
206+
find_reducer(?ki, ?cc) {
148207
auto c;
208+
auto k = str::unsafe_from_bytes_ivec(ki);
209+
// log_err "finding reducer for " + k;
149210
alt(reducers.find(k)) {
150-
case(some(?_c)) { c = _c; }
151-
case(none) {
211+
some(?_c) {
212+
// log_err "reusing existing reducer for " + k;
213+
c = _c;
214+
}
215+
none {
216+
// log_err "creating new reducer for " + k;
152217
auto p = port();
153-
spawn reduce_task(k, chan(p));
218+
tasks += ~[spawn reduce_task(k, chan(p))];
154219
p |> c;
155220
reducers.insert(k, c);
156221
}
157222
}
158-
cc <| c;
223+
cc <| clone(c);
159224
}
160225
}
161226
}
162227

163228
for each(@tup(str, chan[reduce_proto]) kv in reducers.items()) {
229+
// log_err "sending done to reducer for " + kv._0;
164230
kv._1 <| done;
165231
}
232+
233+
// log_err #fmt("joining %u tasks", ivec::len(tasks));
234+
for (task t in tasks) {
235+
task::join(t);
236+
}
237+
// log_err "control task done.";
166238
}
167239
}
168240

@@ -174,7 +246,14 @@ fn main(vec[str] argv) {
174246
fail;
175247
}
176248

249+
auto start = time::precise_time_ns();
177250
map_reduce::map_reduce(vec::slice(argv, 1u, vec::len(argv)));
251+
auto stop = time::precise_time_ns();
252+
253+
auto elapsed = stop - start;
254+
elapsed /= 1000000u64;
255+
256+
log_err "MapReduce completed in " + u64::str(elapsed) + "ms";
178257
}
179258

180259
fn read_word(io::reader r) -> option[str] {

trunk/src/test/run-pass/hashmap-memory.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ mod map_reduce {
4141

4242
fn map_task(chan[ctrl_proto] ctrl,
4343
str input) {
44-
44+
4545
auto intermediates = map::new_str_hash();
4646

4747
fn emit(&map::hashmap[str, int] im,
@@ -85,7 +85,7 @@ mod map_reduce {
8585
while(num_mappers > 0) {
8686
auto m;
8787
ctrl |> m;
88-
88+
8989
alt(m) {
9090
case(mapper_done) { num_mappers -= 1; }
9191
case(find_reducer(?k, ?cc)) {

0 commit comments

Comments
 (0)