workers of the web - braziljs 2013
DESCRIPTION
Concurrency in JavaScript, the potential and limitations.TRANSCRIPT
Thibault ImbertGroup Product Manager | Web Platform
Workers of the WebThibault Imbert@thibault_imbert
Friday, August 23, 13
Records
Friday, August 23, 13
Brazilian disco-funk
Friday, August 23, 13
Brazilian disco-funk
Friday, August 23, 13
Brazilian disco-funk
Friday, August 23, 13
Brazilian disco-funk
Friday, August 23, 13
Brazil’s food
Friday, August 23, 13
Brazil’s food
Friday, August 23, 13
Brazil
Friday, August 23, 13
Estou me mudando para o Brasil
Friday, August 23, 13
Adobe & the web?
Friday, August 23, 13
Adobe & the web?
http://html.adobe.com/webplatform/
Friday, August 23, 13
Friday, August 23, 13
JavaScript concurrency
Friday, August 23, 13
JavaScript concurrencyMultithreading
Friday, August 23, 13
A single threaded world
Friday, August 23, 13
Examples
Friday, August 23, 13
Your budget
1000ms / 60fps = 16.67ms
Friday, August 23, 13
A frame
Rendering (repaint, reflow, etc.)
Network (XHR)
JavaScript (misc logic)6ms
2ms
8ms
16ms
UI Thread
Friday, August 23, 13
The budget
6ms
2ms
8ms
Budget
16ms
Rendering (repaint, reflow, etc.)
Network (XHR)
JavaScript (misc logic)
UI Thread
Friday, August 23, 13
12ms
4ms
10ms
Budget
Over budget
26ms
Rendering (repaint, reflow, etc.)
Network (XHR)
JavaScript (misc logic)
UI Thread
Friday, August 23, 13
Over budget
12ms
4ms
10ms
Budget
10ms
Rendering (repaint, reflow, etc.)
Network (XHR)
JavaScript (misc logic)
26ms
UI Thread
UI Impact
Friday, August 23, 13
6ms
4ms
20ms
Budget
Over budget
30ms
Rendering (repaint, reflow, etc.)
Network (XHR)
JavaScript (misc logic)
UI impact
UI Thread
Friday, August 23, 13
Dev tools
Time spent
Impact on fps
Friday, August 23, 13
So how do we fix that?
Friday, August 23, 13
Web Workers
Friday, August 23, 13
Support
Friday, August 23, 13
Detection
Friday, August 23, 13
Detection
function supports_web_workers() { return window.Worker != null;}
Friday, August 23, 13
Detection
function supports_web_workers() { return window.Worker != null;}
if (Modernizr.webworkers) { // Workers are available} else { // fallback}
Friday, August 23, 13
Most common use case
1. Responsive programming
When you have an expensive computation to perform and don’t want to block the UI.
Friday, August 23, 13
By default, the UI thread
Rendering
Network
JavaScript6ms
2ms
8ms
16ms
UI Thread
Friday, August 23, 13
In parallel
Rendering
Network
JavaScript6ms
2ms
8ms
16ms
UI Thread(Thread 1)
10ms
Web Worker(Thread 2)
JavaScript
Friday, August 23, 13
In parallel
Rendering
Network
JavaScript6ms
2ms
8ms
16ms 28ms
JavaScript
UI Thread(Thread 1)
Web Worker(Thread 2)
Network
Friday, August 23, 13
In parallel
Rendering
Network
JavaScript6ms
2ms
8ms
16ms 44ms
JavaScript
UI Thread(Thread 1)
Web Worker(Thread 2)
Network
Friday, August 23, 13
In parallel
Rendering
Network
JavaScript6ms
2ms
8ms
16ms 44ms
UI Thread(Thread 1)
Web Worker(Thread 2)
Loading remote data
Parsing of XHR dataEncoding/DecodingPhysicsAI (pathfinding, etc.)
Friday, August 23, 13
Life as a worker
What is available:
XMLHttpRequestThe Application Cache
Spawning other web workersThe navigator object
The location object (read-only)setTimeout()/clearTimeout() and setInterval()/clearInterval()
Importing external scripts using the importScripts() method
What is not:
The DOMThe window object
The document objectThe parent object
Friday, August 23, 13
Web Workers == Threads ?
Workers and threads
Friday, August 23, 13
1. Workers are higher-level than threads and safe
First difference
Friday, August 23, 13
Why not threads?
Threads are hard to use.
Too low-level for web development.
We should not expose that level of complexity to web developers.
Locks, manual synchronization, race conditions, really?
Friday, August 23, 13
var worker = new Worker("background.js");
JS VM Impact on memorySlow instantiation time
Thread
Higher-level than threads
Own heap and stack
Friday, August 23, 13
2. Data passing
Second difference
Friday, August 23, 13
Threads and memory
Shared memory
Thread 2
Thread 5
Thread 1
Thread 4
Thread 3
Friday, August 23, 13
Threads and memory
Shared memory
Thread 2
Thread 5
Thread 1
Thread 4
Thread 3
Friday, August 23, 13
Threads and memory
Friday, August 23, 13
With Web Workers, nothing is shared
var worker1 = new Worker("background-task-1.js");
var worker3 = new Worker("background-task-3.js");
var worker2 = new Worker("background-task-2.js");
Cloning
Cloning
Transfer of ownership
Friday, August 23, 13
1 Web Worker == 1 core ?
Workers and cores
Friday, August 23, 13
Workers and cores
UI Thread(Thread 1)
Web Worker(Thread 2)
Tim
e
Single CPU
Friday, August 23, 13
Workers and cores
Tim
e
Multicore CPU
UI Thread(Thread 1)
Web Worker(Thread 2)
Friday, August 23, 13
Workers and cores
Friday, August 23, 13
Workers and cores
1. It is not possible to specify if a Web Worker should run on a specific core.
Friday, August 23, 13
Workers and cores
1. It is not possible to specify if a Web Worker should run on a specific core.
2. Web Workers on a single core CPU, will not run in parallel but will still not block the UI.
Friday, August 23, 13
Workers and cores
1. It is not possible to specify if a Web Worker should run on a specific core.
2. Web Workers on a single core CPU, will not run in parallel but will still not block the UI.
3. On a multicore CPU, Web Workers can run truly in parallel if the OS decides to.
Friday, August 23, 13
mostra o código!
Friday, August 23, 13
Creating a worker
// create a new workervar worker = new Worker("background.js");
Friday, August 23, 13
Background logic
self.postMessage('Hello from Web Worker!');
// create a new workervar worker = new Worker("background.js");
Current worker
Friday, August 23, 13
Background logic
self.postMessage('Hello from Web Worker!');
// create a new workervar worker = new Worker("background.js");
Current worker Send data
Friday, August 23, 13
Background logic
self.postMessage('Hello from Web Worker!');
// create a new workervar worker = new Worker("background.js");
// listen to the response from the Workerworker.addEventListener('message', receiveMessage); // callback handling the response, data is available in the event object// outputs: Hello from Web Worker!function receiveMessage (e){ console.log (e.data);}
Current worker Send data
Friday, August 23, 13
Catching errors
var width = document.innerWidth;self.postMessage(width);
// create a new workervar worker = new Worker("background.js");
// listen to the response from the Workerworker.addEventListener('error', receiveMessage); // callback handling the error// outputs: Uncaught ReferenceError: document is not definedfunction receiveMessage (e){ console.log (e.data);}
Trying to access an object not available from a Worker
Friday, August 23, 13
Data types supported for communication
Friday, August 23, 13
Data types supported for communication
Primitive types: Number, String, Boolean.
Friday, August 23, 13
Data types supported for communication
Primitive types: Number, String, Boolean.
Composite data types: plain JSON objects, ImageData and TypedArray types.
Friday, August 23, 13
Running expensive computation
// create a new workervar worker = new Worker("background.js");
// listen to the response from the Workerworker.addEventListener('message', receiveMessage); // callback handling the response, data is available in the event object// outputs: 400000000function receiveMessage (e){ console.log (e.data);}
var slowSquare = function (n) { var i = 0; while (++i < n * n) {} return i;};
self.postMessage ( slowSquare( 20000 ) );
Friday, August 23, 13
Examples
Friday, August 23, 13
Data cloning
self.postMessage('Hello from Web Worker!');
self.postMessage([1, 13, 34, 50]);
self.postMessage({name: Bob, age: 30});
self.postMessage([{name: Tom, age: 20}]);
Friday, August 23, 13
Data cloning
Web Worker A Web Worker B
clone
Friday, August 23, 13
Data cloning
var data = [1, 2, 3, 4]
Web Worker A Web Worker B
clone
Friday, August 23, 13
Data cloning
var data = [1, 2, 3, 4]self.postMessage(data);
Web Worker A Web Worker B
clone
Friday, August 23, 13
Data cloning
var data = [1, 2, 3, 4]self.postMessage(data);
Web Worker A Web Worker B
[1, 13, 34, 50]clone
Friday, August 23, 13
Data cloning
var data = [1, 2, 3, 4]self.postMessage(data);
Web Worker A Web Worker B
[1, 13, 34, 50]clone
data[2] = 100;
Friday, August 23, 13
Data cloning
var data = [1, 2, 3, 4]self.postMessage(data);
Web Worker A Web Worker B
[1, 13, 34, 50]clone
var incomingArray = e.data;
data[2] = 100;
Friday, August 23, 13
Data cloning
var data = [1, 2, 3, 4]self.postMessage(data);
Web Worker A Web Worker B
[1, 13, 34, 50]clone
var incomingArray = e.data;// outputs: [1, 2, 3, 4] console.log (incomingArray);data[2] = 100;
Friday, August 23, 13
Data cloning
var data = [1, 2, 3, 4]self.postMessage(data);
Web Worker A Web Worker B
[1, 13, 34, 50]clone
var incomingArray = e.data;// outputs: [1, 2, 3, 4] console.log (incomingArray);data[2] = 100;
Overhead
Friday, August 23, 13
Sending a 16mb typedarray with cloning
// Create a 16MB "file" and fill it.var uInt8View = new Uint8Array(1024*1024*16);for (var i = 0; i < uInt8View.length; ++i) { uInt8View[i] = i;}
// transfer ownership to the workerworker.postMessage(uInt8View.buffer);
Friday, August 23, 13
Platform Time (ms)
iOS7 (Safari/iPhone 5) 214
iOS6 (Safari/iPhone 4S) 524
MacBook Pro (Chrome/10.8.4) 75
Sending a 16mb typedarray
Friday, August 23, 13
Transfer of ownership
// Create a 16MB "file" and fill it.var uInt8View = new Uint8Array(1024*1024*16);for (var i = 0; i < uInt8View.length; ++i) { uInt8View[i] = i;}
// transfer ownership to the workerworker.postMessage(uInt8View.buffer, [uInt8View.buffer]);
Friday, August 23, 13
Transfer of ownership
Web Worker A Web Worker B
reference transferred to Web Worker B
Friday, August 23, 13
Transfer of ownership
var data = [1, 2, 3, 4]
Web Worker A Web Worker B
reference transferred to Web Worker B
Friday, August 23, 13
Transfer of ownership
var data = [1, 2, 3, 4]self.postMessage(uInt8View.buffer,
Web Worker A Web Worker B
reference transferred to Web Worker B
Friday, August 23, 13
Transfer of ownership
var data = [1, 2, 3, 4]self.postMessage(uInt8View.buffer, [uInt8View.buffer]);
Web Worker A Web Worker B
reference transferred to Web Worker B
Friday, August 23, 13
Transfer of ownership
var data = [1, 2, 3, 4]self.postMessage(uInt8View.buffer, [uInt8View.buffer]);
Web Worker A Web Worker B
reference transferred to Web Worker B
// triggers runtime exceptionuInt8View.buffer = 12;
Friday, August 23, 13
Transfer of ownership
var data = [1, 2, 3, 4]self.postMessage(uInt8View.buffer, [uInt8View.buffer]);
Web Worker A Web Worker B
reference transferred to Web Worker B
var incomingArray = e.data;
// triggers runtime exceptionuInt8View.buffer = 12;
Friday, August 23, 13
Transfer of ownership
var data = [1, 2, 3, 4]self.postMessage(uInt8View.buffer, [uInt8View.buffer]);
Web Worker A Web Worker B
reference transferred to Web Worker B
var incomingArray = e.data;// outputs: [1, 2, 3, 4] console.log (incomingArray);
// triggers runtime exceptionuInt8View.buffer = 12;
Friday, August 23, 13
Transfer of ownership, almost a 3x boost
Platform Time (ms)
iOS7 (Safari/iPhone 5) 80 (was 214)
iOS6 (Safari/iPhone 4S) 162 (was 524)
MacBook Pro (Chrome/10.8.4) 37 (was 75)
Friday, August 23, 13
Exciting use case
Friday, August 23, 13
Exciting use case
2. Parallel programming
Friday, August 23, 13
Exciting use case
2. Parallel programming
When you want to leverage multiple CPU cores by having computations running concurrently to solve a
specific task.
Friday, August 23, 13
Parallelization
Friday, August 23, 13
Parallelization
Friday, August 23, 13
Parallelization
Worker 1 Worker 2
Worker 4Worker 3
Friday, August 23, 13
But...
Friday, August 23, 13
But...
1. Cloning overhead is high and limits parallelization opportunities.
Friday, August 23, 13
But...
1. Cloning overhead is high and limits parallelization opportunities.
2. Transfer of ownership does not work for parallelization.
Friday, August 23, 13
But...
1. Cloning overhead is high and limits parallelization opportunities.
2. Transfer of ownership does not work for parallelization.
3. A more efficient communication model has to be designed for Web Workers to allow faster
communication.
Friday, August 23, 13
But...
1. Cloning overhead is high and limits parallelization opportunities.
2. Transfer of ownership does not work for parallelization.
3. A more efficient communication model has to be designed for Web Workers to allow faster
communication. Software transactional memory?
Friday, August 23, 13
Friday, August 23, 13
OK, let’s see if you remember the main points.
Friday, August 23, 13
To summarize
1. Leverage Web Workers if you don’t want your UI to lock: true or false?
2. Web Workers are available pretty much everywhere on desktop and mobile: true or false?
3. Web Workers are as low-level as threads: true or false?
4. Message cloning is faster than transfer of ownership: true or false?
5. Web Workers work great to keep the UI responsive: true or false?
6. Parallel programming and responsive programming are the same things: true or false?
Friday, August 23, 13
To summarize
1. Leverage Web Workers if you don’t want your UI to lock: true or false?
2. Web Workers are available pretty much everywhere on desktop and mobile: true or false?
3. Web Workers are as low-level as threads: true or false?
4. Message cloning is faster than transfer of ownership: true or false?
5. Web Workers work great to keep the UI responsive: true or false?
6. Parallel programming and responsive programming are the same things: true or false?
Friday, August 23, 13
To summarize
1. Leverage Web Workers if you don’t want your UI to lock: true or false?
2. Web Workers are available pretty much everywhere on desktop and mobile: true or false?
3. Web Workers are as low-level as threads: true or false?
4. Message cloning is faster than transfer of ownership: true or false?
5. Web Workers work great to keep the UI responsive: true or false?
6. Parallel programming and responsive programming are the same things: true or false?
Friday, August 23, 13
To summarize
1. Leverage Web Workers if you don’t want your UI to lock: true or false?
2. Web Workers are available pretty much everywhere on desktop and mobile: true or false?
3. Web Workers are as low-level as threads: true or false?
4. Message cloning is faster than transfer of ownership: true or false?
5. Web Workers work great to keep the UI responsive: true or false?
6. Parallel programming and responsive programming are the same things: true or false?
Friday, August 23, 13
To summarize
1. Leverage Web Workers if you don’t want your UI to lock: true or false?
2. Web Workers are available pretty much everywhere on desktop and mobile: true or false?
3. Web Workers are as low-level as threads: true or false?
4. Message cloning is faster than transfer of ownership: true or false?
5. Web Workers work great to keep the UI responsive: true or false?
6. Parallel programming and responsive programming are the same things: true or false?
Friday, August 23, 13
To summarize
1. Leverage Web Workers if you don’t want your UI to lock: true or false?
2. Web Workers are available pretty much everywhere on desktop and mobile: true or false?
3. Web Workers are as low-level as threads: true or false?
4. Message cloning is faster than transfer of ownership: true or false?
5. Web Workers work great to keep the UI responsive: true or false?
6. Parallel programming and responsive programming are the same things: true or false?
Friday, August 23, 13
To summarize
1. Leverage Web Workers if you don’t want your UI to lock: true or false?
2. Web Workers are available pretty much everywhere on desktop and mobile: true or false?
3. Web Workers are as low-level as threads: true or false?
4. Message cloning is faster than transfer of ownership: true or false?
5. Web Workers work great to keep the UI responsive: true or false?
6. Parallel programming and responsive programming are the same things: true or false?
Friday, August 23, 13
@thibault_imbert
Blog: typedarray.org
obrigado!
Slides: http://bit.ly/13Lbk8d/More details: http://bit.ly/14IWKKj
Friday, August 23, 13