For anyone that is interested in easily using WebWorkers for this sort of work please check out task.js (<a href="https://github.com/icodeforlove/task.js" rel="nofollow">https://github.com/icodeforlove/task.js</a>).<p>It allows you to send a pure function with provided arguments to a autoscaling WebWorker pool.<p>Heres a similar demo (<a href="http://s.codepen.io/icodeforlove/debug/ZOjBBB" rel="nofollow">http://s.codepen.io/icodeforlove/debug/ZOjBBB</a> , you can bring all cores to 100% usage)<p>But for this specific scenario it could have been coded like this using task.js (vs <a href="http://afshinm.github.io/50k/worker.js" rel="nofollow">http://afshinm.github.io/50k/worker.js</a> which is not reusable)<p><pre><code> // mentioned sort function (close to exact code from site)
function bubbleSort(a) {
var swapped;
do {
swapped = false;
for (var i=0; i < a.length-1; i++) {
if (a[i] > a[i+1]) {
var temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
swapped = true;
}
}
} while (swapped);
return a;
}
// turn the function into a worker task
const bubbleSortAsync = task.wrap(bubbleSort);
// this now runs in a autoscaling worker pool (first run includes worker initialization time)
console.time('BubbleSort Worker');
bubbleSortAsync([9,1,2,3]).then(sortedArray => {
console.timeEnd('BubbleSort Worker');
}, error => { /* this is extra credit, yes we can handle worker errors */ });
</code></pre>
Also when dealing with large messages you can use transferables (<a href="https://developer.mozilla.org/en-US/docs/Web/API/Transferable" rel="nofollow">https://developer.mozilla.org/en-US/docs/Web/API/Transferabl...</a>).<p>The web has really came a long way, this kind of stuff is extremely useful, for instance you could use it when processing pixel data for a 10MP image with a RGBA array of 40M. In that scenario the work can be spread across all cores, and blows away the alternate approach of just locking the UI. In that case if you were using task.js you would just chunk the work, and use a async control flow library like bluebird.<p><pre><code> // in this situation all cores would be at 100% without locking the UI
let processedPixels = await Promise.map(chunks, processPixelChunkAsync);</code></pre>
Although the web worker version is slower, the fact that it doesn't block UI is a huge gain.<p>I tried to see if I could make the bubble sort function async as to not block the browser UI using callbacks as opposed to workers. Here's a (messy) fiddle for those that want to check it out: <a href="https://jsfiddle.net/tbinetruy/8q1de9jk/" rel="nofollow">https://jsfiddle.net/tbinetruy/8q1de9jk/</a> (watch out, this fiddle runs the blocking bubble sort on a 50k array on page load, so it'll freeze your UI for 5 seconds. Then the non-blocking sort kicks in and your UI becomes usable again).<p>For a 50k array, the blocking code ran in 6.682s and the non-blocking code in 9.297s (when I ran it locally just now anyway). I added a clickable button and update the DOM every 25ms with a random number to show the user what the non blocking code allows for.<p>The same type of non blocking code without relying on web workers should also be possible with async functions and promises. I'll have to look into it.
On Android Chrome the web worker took 18 seconds while the non web worker took 11 seconds but was utterly unresponsive. Having a responsive ui using the web worker with later results than a non responsive ui with faster results is a trade off I'll take any day.
I must be silly but I expected the web worker version to run faster. I must have understood "many threads". It ran nearly 200ms slower :)<p>That said, not locking the UI thread and showing user feedback is totally worth 200ms extra for most tasks.
For anyone familiar with the landscape:<p>Are webworkers likely to improve dramatically as time goes on? For example, the cost of using web workers <i>appears</i>[1] to be far greater than just spinning up another thread in, say, Go[2]. I assume this is mainly due to how the browser is sandboxing JS. So, is there room for improvement here? Or have most things js related been so drastically optimized that we are without much hope here?<p>[1]: Purely speculative on my part.
[2]: Yes i know Go has green threads, it's purely an example. I was going to say Rust, but that seems like an unfair comparison.
Cool demo! Web Workers are nice, and well supported by the evergreen browswers. Lots of apps do CPU intensive stuff on the server though and don't actually need them.<p>I am more interested in "Shared Web Workers", since it would allow for synchronization between tabs. It's got pretty poor support though, only Firefox, Chrome desktop, and Opera :(
Oh my, I was given the impossible task of writing a hardware resource allocation algorithm to produce encoding XML config from the UI in JavaScript. Think of a hardware device needing to efficiently transcode 80 SD or 12 HD (mix and match) video streams (plus audio - stereo/dolby) on varying encode cards (6 max), all from a drag and drop interface and without disrupting existing encoding allocations to prevent glitches while it reconfigures.<p>Long story short, this had to work in IE8 and not block the UI to get it done and no plugins. I wrote some crazy way of doing the work in chunks using a setTimeout to get it complete. The project was a success but I stated very firmly that this was a job for the device, not the UI in future versions. Hard when the device in question only had a 300MHz CPU.<p>Those were the days.
2.8 seconds without
3.3 seconds with webworker<p>Imho not acceptable trade-off, did not hear the term web workers yet, and now i'm not even upset i did not and probably will never....
Web Workers are such a disaster of a terrible API. I can't believe actual programmers came up with that syntax.<p>Passing strings and <i>filenames</i> around, what were they thinking?