Skip to content

Instantly share code, notes, and snippets.

@mourner
Created June 10, 2020 17:45
Show Gist options
  • Select an option

  • Save mourner/442e65ca838d797e89f591c94b81204f to your computer and use it in GitHub Desktop.

Select an option

Save mourner/442e65ca838d797e89f591c94b81204f to your computer and use it in GitHub Desktop.

Revisions

  1. mourner created this gist Jun 10, 2020.
    82 changes: 82 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,82 @@
    <!DOCTYPE html>
    <html>
    <head>
    <title>Worker Test</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
    #log { font: 14px monospace; }
    </style>
    </head>
    <body>
    <div id="log"></div>
    <script>

    async function runBench(numWorkers, done) {
    return new Promise(resolve => {
    const start = Date.now();

    const workers = [];
    const results = [];
    let numFinished = 0;

    for (let i = 0; i < numWorkers; i++) {
    const worker = new Worker('./worker.js');
    worker.onmessage = (e) => {
    results.push(e.data);
    worker.terminate();
    if (++numFinished === numWorkers) {
    resolve(results);
    }
    }
    worker.postMessage(start);
    workers[i] = worker;
    }
    });
    }

    let frameId;

    function frame() {
    const start = performance.now();
    while (performance.now() - start < 15) {}
    frameId = requestAnimationFrame(frame);
    }

    frameId = requestAnimationFrame(frame);

    function log(msg) {
    const logEl = document.getElementById('log');
    logEl.innerHTML += `${msg}<br>`;
    }

    (async () => {
    log(`hardwareConcurrency: ${navigator.hardwareConcurrency}<br>`);
    const maxWorkers = 8;

    await runBench(1); // warmup

    let baseline, baselineWork;
    for (let numWorkers = 1; numWorkers <= maxWorkers; numWorkers++) {
    log(`Running ${numWorkers} workers:`);
    const start = Date.now();
    const times = await runBench(numWorkers);
    const total = Date.now() - start;
    if (numWorkers === 1) {
    baseline = total;
    baselineWork = times[0].work;
    }
    for (const [i, {init, work}] of Object.entries(times)) {
    log(`worker ${i}: ${init}ms init + ${work}ms work`);
    }
    log(`first result: ${times[0].init + times[0].work}ms`);
    log(`single slowdown: ${(times[0].work / baselineWork).toLocaleString()}x`);
    log(`parallel speedup: ${(numWorkers * baseline / total).toLocaleString()}x<br>`);
    }
    log('done');
    cancelAnimationFrame(frameId);
    })();

    </script>
    </body>
    </html>
    41 changes: 41 additions & 0 deletions worker.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,41 @@

    function* primes() {
    yield 2; yield 3; yield 5; yield 7;

    const sieve = new Map();
    const ps = primes();
    ps.next();
    ps.next();

    for (let p = 3, i = 9; true; i += 2) {
    let s = sieve.get(i);

    if (s !== undefined) {
    sieve.delete(i);
    } else if (i < p * p) {
    yield i;
    continue;
    } else {
    s = 2 * p;
    p = ps.next().value;
    }

    let k = i + s;
    while (sieve.has(k)) k += s;
    sieve.set(k, s);
    }
    }

    const N = 1000000;

    onmessage = (e) => {
    const start = Date.now();
    const init = start - e.data;

    const ps = primes();
    for (let i = 0; i < N; i++) ps.next();

    const work = Date.now() - start;

    self.postMessage({init, work});
    }