Skip to content

Commit c7e9671

Browse files
author
Eric Holk
committed
Task-ified the word count program.
This meant most of the generic-ness of it had to go away, since our type system doesn't quite support it yet. Hopefully someday... This version has lots of memory management errors. My next commit will hopefully fix these.
1 parent 0cacbe9 commit c7e9671

File tree

1 file changed

+117
-53
lines changed

1 file changed

+117
-53
lines changed

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

Lines changed: 117 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,35 @@ import std::str;
1818
import std::vec;
1919
import std::map;
2020

21+
fn map(str filename, map_reduce::putter emit) {
22+
auto f = io::file_reader(filename);
23+
24+
while(true) {
25+
alt(read_word(f)) {
26+
case (some(?w)) {
27+
emit(w, "1");
28+
}
29+
case (none) {
30+
break;
31+
}
32+
}
33+
}
34+
}
35+
36+
fn reduce(str word, map_reduce::getter get) {
37+
auto count = 0;
38+
39+
while(true) {
40+
alt(get()) {
41+
case(some(_)) { count += 1 }
42+
case(none) { break }
43+
}
44+
}
45+
46+
auto out = io::stdout();
47+
out.write_line(#fmt("%s: %d", word, count));
48+
}
49+
2150
mod map_reduce {
2251
export putter;
2352
export getter;
@@ -33,84 +62,119 @@ mod map_reduce {
3362

3463
type reducer = fn(str, getter);
3564

65+
tag ctrl_proto {
66+
find_reducer(str, chan[chan[reduce_proto]]);
67+
mapper_done;
68+
}
69+
70+
tag reduce_proto {
71+
emit_val(str);
72+
done;
73+
}
74+
75+
fn start_mappers(chan[ctrl_proto] ctrl,
76+
vec[str] inputs) {
77+
for(str i in inputs) {
78+
spawn map_task(ctrl, i);
79+
}
80+
}
81+
82+
fn map_task(chan[ctrl_proto] ctrl,
83+
str input) {
3684

37-
fn map_reduce (vec[str] inputs,
38-
mapper f,
39-
reducer reduce) {
40-
auto intermediates = map::new_str_hash[vec[str]]();
85+
auto intermediates = map::new_str_hash();
4186

42-
fn emit(&map::hashmap[str, vec[str]] im,
87+
fn emit(&map::hashmap[str, chan[reduce_proto]] im,
88+
chan[ctrl_proto] ctrl,
4389
str key, str val) {
44-
auto old = [];
45-
alt(im.remove(key)) {
46-
case (some(?v)) {
47-
old = v;
90+
auto c;
91+
alt(im.find(key)) {
92+
case(some(?_c)) {
93+
c = _c
94+
}
95+
case(none) {
96+
auto p = port[chan[reduce_proto]]();
97+
ctrl <| find_reducer(key, chan(p));
98+
p |> c;
99+
im.insert(key, c);
48100
}
49-
case (none) { }
50101
}
51-
52-
im.insert(key, old + [val]);
102+
c <| emit_val(val);
53103
}
54104

55-
for (str i in inputs) {
56-
f(i, bind emit(intermediates, _, _));
57-
}
105+
map(input, bind emit(intermediates, ctrl, _, _));
106+
ctrl <| mapper_done;
107+
}
58108

59-
fn get(vec[str] vals, &mutable uint i) -> option[str] {
60-
i += 1u;
61-
if(i <= vec::len(vals)) {
62-
some(vals.(i - 1u))
63-
}
64-
else {
65-
none
109+
fn reduce_task(str key, chan[chan[reduce_proto]] out) {
110+
auto p = port();
111+
112+
out <| chan(p);
113+
114+
fn get(port[reduce_proto] p) -> option[str] {
115+
auto m;
116+
p |> m;
117+
118+
alt(m) {
119+
case(emit_val(?v)) { ret some(v); }
120+
case(done) { ret none; }
66121
}
67122
}
68123

69-
for each (@tup(str, vec[str]) kv in intermediates.items()) {
70-
auto i = 0u;
71-
reduce(kv._0, bind get(kv._1, i));
72-
}
124+
reduce(key, bind get(p));
73125
}
74-
}
75126

76-
fn main(vec[str] argv) {
77-
if(vec::len(argv) < 2u) {
78-
auto out = io::stdout();
127+
fn map_reduce (vec[str] inputs) {
128+
auto ctrl = port[ctrl_proto]();
79129

80-
out.write_line(#fmt("Usage: %s <filename> ...", argv.(0)));
81-
fail;
82-
}
130+
// This task becomes the master control task. It spawns others
131+
// to do the rest.
83132

84-
fn map(str filename, map_reduce::putter emit) {
85-
auto f = io::file_reader(filename);
133+
let map::hashmap[str, chan[reduce_proto]] reducers;
86134

87-
while(true) {
88-
alt(read_word(f)) {
89-
case (some(?w)) {
90-
emit(w, "1");
91-
}
92-
case (none) {
93-
break;
135+
reducers = map::new_str_hash();
136+
137+
start_mappers(chan(ctrl), inputs);
138+
139+
auto num_mappers = vec::len(inputs) as int;
140+
141+
while(num_mappers > 0) {
142+
auto m;
143+
ctrl |> m;
144+
145+
alt(m) {
146+
case(mapper_done) { num_mappers -= 1; }
147+
case(find_reducer(?k, ?cc)) {
148+
auto c;
149+
alt(reducers.find(k)) {
150+
case(some(?_c)) { c = _c; }
151+
case(none) {
152+
auto p = port();
153+
spawn reduce_task(k, chan(p));
154+
p |> c;
155+
reducers.insert(k, c);
156+
}
157+
}
158+
cc <| c;
94159
}
95160
}
96161
}
97-
}
98162

99-
fn reduce(str word, map_reduce::getter get) {
100-
auto count = 0;
101-
102-
while(true) {
103-
alt(get()) {
104-
case(some(_)) { count += 1 }
105-
case(none) { break }
106-
}
163+
for each(@tup(str, chan[reduce_proto]) kv in reducers.items()) {
164+
kv._1 <| done;
107165
}
166+
}
167+
}
108168

169+
fn main(vec[str] argv) {
170+
if(vec::len(argv) < 2u) {
109171
auto out = io::stdout();
110-
out.write_line(#fmt("%s: %d", word, count));
172+
173+
out.write_line(#fmt("Usage: %s <filename> ...", argv.(0)));
174+
fail;
111175
}
112176

113-
map_reduce::map_reduce(vec::slice(argv, 1u, vec::len(argv)), map, reduce);
177+
map_reduce::map_reduce(vec::slice(argv, 1u, vec::len(argv)));
114178
}
115179

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

0 commit comments

Comments
 (0)