mhadaily
Web Workers
Web Assembly
Service Worker
Parallel Computing VS Concurrency
mhadaily
Worklets
mhadaily
Web Workers
Web Assembly
Service Worker
Parallel Computing VS Concurrency
mhadaily
Worklets
import HelloWorld from "@/components/HelloWorld.component";
export default {
name: "whoAmI",
data: {
me: {
name: "Majid Hajian",
location: "Oslo, Norway",
description: ```
Passionate Software engineer,
Community Leader, Author and international Speaker
```,
main: "Web, Javascripter, Flutter/Dart, IoT",
homepage: "https://www.majidhajian.com",
socials: {
twitter: "https://www.twitter.com/mhadaily",
github: "https://www.github.com/mhadaily"
},
books: {
"Progressive Web App with Angular": {
version: "1.0.0",
publishedBy: "Apress",
foundOn: "www.pwawithangular.com",
}
},
author: {
packtpub: "PWA development, 7 hours video course",
Udemy: "PWA development, 7 hours video course"
}
founder: "Softiware As (www.Softiware.com)"
devDependencies: {
tea: "green", mac: "10.14+",
},
engines: {
VueJsOslo: "Orginizer", MobileEraConference: "Orginizer",
ngVikingsConference: "Orginizer",
MobileMeetupOslo:"Co-Orginizer",AngularOslo: "Co-Orginizer",
FlutterDartOslo: "Co-Orginizer",Framsia: "Co-Orginizer",
}};}
};
Find me on the internet by
mhadaily
mhadaily
Thread is not equal to CPU core
mhadaily
mhadaily
Javascript code
mouse event
other event
other event
Event queue
mhadaily
mhadaily
Javascript code
mouse event
Some other event
other event
mhadaily
mhadaily
Spwan another instance of the JS Engine
Runs in worker thread
No shared state
Communicate vis msg
Have their own event(msg) queue
No access to dom & window obj
Javascript code
msg
msg
mouse event
other event
some other event
Browser Event Queue
Web Worker Message Queue
mhadaily
mhadaily
Javascript code
msg
msg
mouse event
other event
some other event
Browser Event Queue
Web Worker Message Queue
mhadaily
mhadaily
Task Parallelism?
Javascript code
msg
msg
mouse event
other event
some other event
Browser Event Queue
Web Worker Message Queue
Core 2
Core 1
mhadaily
mhadaily
mhadaily
mhadaily
postMessage
Main Thread
Worker Thread
mhadaily
mhadaily
// Main
const worker = new Worker("./worker.js");
let counter = 0;
setInterval(() => {
counter = counter + 1;
worker.postMessage({ action: "power2", payload: counter });
}, 3000);
mhadaily
mhadaily
// Worker
self.onmessage = message => {
const { data } = message;
switch (data.action) {
case "power2":
const number = data.payload;
const power2 = number * number;
self.postMessage({ command: "power2", payload: power2 });
break;
}
};
mhadaily
mhadaily
// Main
const worker = new Worker("./worker.js");
let counter = 0;
setInterval(() => {
counter = counter + 1;
worker.postMessage({ action: "power2", payload: counter });
}, 1000);
worker.onmessage = message => {
const { data } = message;
switch (data.command) {
case "power2":
const power2 = data.value;
console.log("power2: ", power2);
break;
}
};
mhadaily
mhadaily
Main Thread
Worker Thread
function power2(){}
w.power2(5);
const w = new Worker();
mhadaily
mhadaily
mhadaily
mhadaily
// Main
import * as Comlink from "https://unpkg.com/comlink@alpha/dist/esm/comlink.mjs";
// import * as Comlink from "../../../dist/esm/comlink.mjs";
async function init() {
const worker = new Worker("./worker.js");
const service = Comlink.proxy(worker);
const power2 = await service.power2(2);
console.log(power2);
const increment = await service.increment(2);
console.log(increment);
}
init();
mhadaily
mhadaily
// Worker
importScripts("https://unpkg.com/comlink@alpha/dist/umd/comlink.js");
// importScripts("../../../dist/umd/comlink.js");
const service = {
power2: value => value * value,
increment: (value) => value * 1
};
Comlink.expose(service);
mhadaily
mhadaily
// all imports
class UsersWrapper extends Component {
worker;
workerService;
constructor(props) {
super(props);
this.state = {
users: [],
};
}
componentDidMount() {
this.worker = new Worker('./worker.js');
this.workerService = Comlink.wrap(worker);
// Assumption is we have a list of 3000 users!
fetchUsers().then(users => {
this.setState({ users });
})
}
async sortAscending() {
const sortedUsers = await this.workerService.sort(this.state.users);
this.setState({ users: sortedUsers });
return;
}
componentDidMount(){
this.worker.terminate();
}
render() {
return this.state.users.slice(0,20).map((user, index) => (<User key={user.id}>);
}
}
mhadaily
mhadaily
// WORKER
// all importScripts();
const service = {
sortDesc(users){},
sortAsc(users) {
for (let i = 0; i < users.length-1; i++) {
for (let j = i+1; j < users.length; j++) {
if (users[i].commentCount > users[j].commentCount) {
const t = users[i];
users[i] = users[j];
users[j] = t;
}
}
}
}
};
Comlink.expose(service);
mhadaily
mhadaily
and
mhadaily
mhadaily
how about Javascript / web developer?
AssemblyScript compiles a strict subset of TypeScript to WebAssembly
npm init
npm install assemblyscript/assemblyscript
npx asinit .
/*
./assembly
Directory holding the AssemblyScript sources being compiled to WebAssembly.
./assembly/tsconfig.json
TypeScript configuration inheriting recommended AssemblyScript settings.
./assembly/index.ts
Exemplary entry file being compiled to WebAssembly to get you started.
./build
Build artifact directory where compiled WebAssembly files are stored.
./build/.gitignore
Git configuration that excludes compiled binaries from source control.
./index.js
Main file loading the WebAssembly module and exporting its exports.
./package.json
Package info containing the necessary commands to compile to WebAssembly.
*/
mhadaily
mhadaily
// The entry file of your WebAssembly module.
export function power2(a: i32): i32 {
return a + a;
}
// no optimization, no memoization
export function fibonacci(num: i32): i32 {
if (num <= 1) return 1;
return fibonacci(num - 1) + fibonacci(num - 2);
}
mhadaily
mhadaily
var int8: i8 = <i8>0; // 8-bit signed integer [-128 to 127]
var uint8: u8 = <u8>0; // 8-bit unsigned integer [0 to 255]
var int16: i16 = <i16>0; // 16-bit signed integer [-32,768 to 32,767]
var uint16: u16 = <u16>0; // 16-bit unsigned integer [0 to 65,535]
var int32: i32 = <i32>0; // 32-bit signed integer [-2,147,483,648 to 2,147,483,647]
var uint32: u32 = <u32>0; // 32-bit unsigned integer [0 to 4,294,967,295]
var int64: i64 = <i64>; // 64-bit signed integer [-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807]
var uint64: i64 = <u64>0; // 64-bit unsigned integer [0 to 18,446,744,073,709,551,615]
var float32: f32 = <f32>0.0; // 32-bit float [32 bit float range]
var float64: f64 = <f64>0.0; // 64-bit float [64 bit float range]
var pointer: usize = <usize>0; // a 32/64-bit pointer to a location in memory
mhadaily
mhadaily
import "allocator/tlsf";
let ptr = memory.allocate(64);
// do something with ptr ...
//
// ... once you are done, make sure you free it again.
memory.free(ptr);
mhadaily
mhadaily
npm run asbuild
/**
Created: ./build/optimized.wasm
Created: ./build/optimized.wasm.map
Created: ./build/optimized.wat
Created: ./build/untouched.wasm
Created: ./build/untouched.wasm.map
Created: ./build/untouched.wat
* /
// untouched.wasm is good for debugging
// optimized.wasm can be used in production
// wat is the text representation of the genrated .wasm
mhadaily
mhadaily
// all other imports
import { instantiateStreaming, ASUtil } from "assemblyscript/lib/loader";
// no optimization, no memoization
function fibonacci(num) {
if (num <= 1) return 1;
return fibonacci(num - 1) + fibonacci(num - 2);
}
class FibWrapper extends Component {
imports = {};
wasmService;
async componentDidMount() {
this.wasmService = await instantiateStreaming(fetch('/optimized.wasm'), this.imports);
}
async factorialwasm() {
const result = await this.wasmService.fibonacci(9999);
this.setState({ number: result });
return;
}
factorialJS() {
const result = fibonacci(9999);
this.setState({ number: result });
return;
}
render() {
return <Fib />;
}
}
mhadaily
mhadaily
mhadaily
mhadaily
WebAssembly was about 7 times faster for the first run
mhadaily
mhadaily
mhadaily
mhadaily
mhadaily
mhadaily
A lightweight version of WebWorkers
Access to low-level parts of rendering pipleline
Run Javascript and WebAssembly
graphic rendering or audio processing
High performance
mhadaily
mhadaily
Paint
Animation
Layout
Audio
(also known as “CSS Custom Paint” or “Houdini’s paint worklet”)
mhadaily
mhadaily
// checkerboard.js
class CheckerboardPainter {
paint(ctx, geom, properties) {
// Use `ctx` as if it was a normal canvas
const colors = ['black', 'white'];
const size = 32;
for(let y = 0; y < geom.height/size; y++) {
for(let x = 0; x < geom.width/size; x++) {
const color = colors[(x + y) % colors.length];
ctx.beginPath();
ctx.fillStyle = color;
ctx.rect(x * size, y * size, size, size);
ctx.fill();
}
}
}
}
// Register our class under a specific name
registerPaint('checkerboard', CheckerboardPainter);
mhadaily
mhadaily
<!-- index.html -->
<!doctype html>
<style>
textarea {
background-image: paint(checkerboard);
}
</style>
<textarea></textarea>
<script>
if (typeof CSS === 'undefined' || !('paintWorklet' in CSS)) {
return;
} else {
CSS.paintWorklet.addModule('checkerboard.js');
}
</script>
mhadaily
mhadaily
mhadaily
mhadaily
mhadaily
mhadaily
All Frameworks
Service Worker in-depth:
mhadaily
mhadaily
mhadaily
mhadaily
A type of Web Worker
Essentially a Javascript File
Runs different Thread & Background
Intercepts network requests
Caching, delivering push msgs
// Register a Service Worker
// index.html
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then( (reg) => console.log(reg))
.catch((error) =>
console.log('Registration failed with ' + error)
);
}
mhadaily
mhadaily
mhadaily
mhadaily
because you can do many things on the fly!
mhadaily
mhadaily
// all imports and workaround by Kenneth Christiansen
// webp_wasm.wasm
self.addEventListener('fetch', async event => {
if (event.request.method != 'GET') return;
if (!event.request.url.endsWith(".webp")) return;
event.respondWith(async function() {
try {
const response = await fetch(event.request);
const buffer = await response.arrayBuffer();
const WebPDecoder = await fetchWebPDecoderWithWorkarounds();
const decoder = new WebPDecoder(buffer);
const blob = await decoder.decodeToBMP();
return new Response(blob, { headers: { "content-type": "image/bmp", "status": 200 } });
} catch(err) {
console.error(err);
}
return fetch(event.request);
}());
});
mhadaily
mhadaily
mhadaily
mhadaily
Web Workers (comlink)
Web Assembly (AssemblyScript)
Service Worker
Worklets (CSS paint API)
Boost User experince
Majid Hajian
mhadaily
Slides and link to source code
bit.ly/parallel-computing-in-react
majid[at]softiware[dot]com