Skip to content

Commit badf5c1

Browse files
committed
Rewrite the parallel raytracing example with rayon
One of the best parts about concurrency in Rust is using `rayon` and how easy it makes parallelization of tasks, so it's the ideal example for parallel Rust on the web! Previously we've been unable to use `rayon` because there wasn't a way to customize how rayon threads themselves are spawned, but [that's now being developed for us][rayon]! This commit uses that PR to rewrite the `raytrace-parallel` example in this repository. While not a perfect idiomatic representation of using `rayon` I think this is far more idiomatic than the previous iteration of `raytrace-parallel`! I'm hoping that we can continue to iterate on this, but otherwise show it off as a good example of parallel Rust on the web. [rayon]: rayon-rs/rayon#636
1 parent d49d8c9 commit badf5c1

File tree

6 files changed

+432
-297
lines changed

6 files changed

+432
-297
lines changed

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,5 @@ wasm-bindgen = { path = '.' }
9292
wasm-bindgen-futures = { path = 'crates/futures' }
9393
js-sys = { path = 'crates/js-sys' }
9494
web-sys = { path = 'crates/web-sys' }
95+
rayon = { git = 'https://github.com/cuviper/rayon', branch = 'custom-spawn' }
96+
rayon-core = { git = 'https://github.com/cuviper/rayon', branch = 'custom-spawn' }

examples/raytrace-parallel/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ crate-type = ["cdylib"]
1111
console_error_panic_hook = "0.1"
1212
futures = "0.1"
1313
js-sys = "0.3.16"
14+
rayon = "1.0.3"
15+
rayon-core = "1.0.3"
1416
raytracer = { git = 'https://github.com/alexcrichton/raytracer', branch = 'update-deps' }
1517
wasm-bindgen = { version = "0.2.39", features = ['serde-serialize'] }
1618
wasm-bindgen-futures = "0.3.16"

examples/raytrace-parallel/index.js

+15-9
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ function run() {
4444

4545
// Configure various buttons and such.
4646
button.onclick = function() {
47+
button.disabled = true;
4748
console.time('render');
4849
let json;
4950
try {
@@ -82,32 +83,38 @@ class State {
8283
this.running = true;
8384
this.counter = 1;
8485

85-
this.interval = setInterval(() => this.updateTimer(), 100);
86+
this.interval = setInterval(() => this.updateTimer(true), 100);
8687

8788
wasm.promise()
88-
.then(() => {
89-
this.updateTimer();
89+
.then(data => {
90+
this.updateTimer(false);
91+
this.updateImage(data);
9092
this.stop();
9193
})
9294
.catch(console.error);
9395
}
9496

95-
updateTimer() {
97+
updateTimer(updateImage) {
9698
const dur = performance.now() - this.start;
9799
timingVal.innerText = `${dur}ms`;
98100
this.counter += 1;
99-
if (this.wasm && this.counter % 3 == 0)
100-
this.wasm.requestUpdate();
101+
102+
if (updateImage && this.wasm && this.counter % 3 == 0)
103+
this.updateImage(this.wasm.imageSoFar());
104+
}
105+
106+
updateImage(data) {
107+
ctx.putImageData(data, 0, 0);
101108
}
102109

103110
stop() {
104111
if (!this.running)
105112
return;
106113
console.timeEnd('render');
107114
this.running = false;
108-
pool = this.wasm.cancel(); // this frees `wasm`, returning the worker pool
109115
this.wasm = null;
110116
clearInterval(this.interval);
117+
button.disabled = false;
111118
}
112119
}
113120

@@ -116,6 +123,5 @@ function render(scene) {
116123
rendering.stop();
117124
rendering = null;
118125
}
119-
rendering = new State(scene.render(concurrency.value, pool, ctx));
120-
pool = null; // previous call took ownership of `pool`, zero it out here too
126+
rendering = new State(scene.render(concurrency.value, pool));
121127
}

0 commit comments

Comments
 (0)