Web Development

HTML5 Web Workers

HTML5 Web Workers provide a new way of performing processor-intensive tasks. Heavy computing has historically been difficult to achieve using JavaScript on the browser. This was due to two things: JavaScript's poor performance and its single threaded nature. The first of these issues has been given a lot of attention in recent years, with browsers competing intensely on JavaScript speed. In the last two years, engines like Chrome's V8 and Safari's Nitro, have made single-threaded performance pretty good.

The second problem was that any long-running computation was interpreted by the browser as a script that should be stopped. This approach was aimed at giving the user a chance to stop misbehaving scripts but also made it difficult to do large amounts of processing. The only real option was to break the tasks into smaller chunks (if possible) and use setTimeout to circumvent this restriction.

While that worked, we now have a better solution in the form of "Web Workers". Workers are typically simple scripts that run in a separate thread. One great benefit of this is that their execution does not block the UI. No matter how much number crunching a worker is doing, the UI remains responsive.

How Web Workers Work

Web Workers exist almost independently of the page that spawned them. The worker has no access to the spawning page's DOM, and cannot communicate with it directly. All communication between the page and the worker is performed asynchronously via callback functions that accept message strings. Let's construct a simple Worker to see how it works:

Above we've created a new Worker by simply calling its constructor with the name of a JavaScript file to load. This is an important and initially surprising part of the design of Workers. However, if a Worker could instead be constructed by passing in a function to execute, it would be trivial to pass in a closure with a reference to the DOM or other page elements, allowing the Worker free access to the spawning page. This threat is greatly diminished, by separating the file and only allowing communication via string messages.

After constructing the Worker, we set up a callback function that accepts an event object. This is the means by which the Worker can communicate with the spawning page. Finally, we post a message to the worker to kick the process off. Let's see what our worker.js looks like:

Our worker is extremely simple and just joins two strings together. We listen for the message that we passed in with the spawning page's call to postMessage by defining the worker's onmessage function. After the trivial processing we perform, the worker calls its own postMessage function, which is picked up by the spawning page in the function that we set on worker.onmessage. The outcome of running this code is that the string, "Worker says: Your name is Dave", is alerted.

Using a Worker for such a simple operation is clearly a case of over-engineering, but the simple processing we performed above can be replaced by almost anything. We could pass worker.js a dataset to transform, an image to analyse or any other intensive computing task.

Workers Everywhere

Of course, we are not limited to spawning a single worker. Large tasks can often be split into smaller subsets in a divide and conquer strategy. This rewards of this approach largely depend on how parallel your processing is -- if you have 100,000 records to process in some way and the processing of each record does not depend on the other, you can spawn a large number of Workers. With the trend towards many-core CPUs set to continue for the foreseeable future, this is clearly a scaleable approach.

A few more interesting facts about Workers: they can spawn each other, talk to each other and even be shared between pages. Recursive algorithms get a boost from this, especially those recursing over tree structures. Each node can be processed by a different worker which reports back to the master worker, which in turn reports back to the spawning page. This is useful as it allows us to move all the multiple-Worker spawning logic into a worker script and keep the page logic simple.

Web Workers are available in Firefox 3.5+, Chrome 4+ and Safari 4+. Web Workers are not supported in any version of Internet Explorer, and at the time of writing it seems they will not be present in IE9 either. Web Workers will be great for speeding up computation on compatible browsers, but a fallback mechanism will be required for the foreseeable future.

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!