Last active
December 26, 2017 05:53
-
-
Save poppycocker/6d591dfce0da3f9580244bf766bb0d0a to your computer and use it in GitHub Desktop.
Web Workers Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>ww</title> | |
<script | |
src="https://code.jquery.com/jquery-3.2.1.min.js" | |
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" | |
crossorigin="anonymous"></script> | |
</head> | |
<body> | |
Count Prime Numbers(of 0 to 200,000) With Web Workers | |
<ul> | |
<li> | |
<button id="run1">run with 1 thread</button> | |
<p id="result1"></p> | |
<p id="durations1"></p> | |
</li> | |
<li> | |
<button id="run2">run with 2 threads</button> | |
<p id="result2"></p> | |
<p id="durations2"></p> | |
</li> | |
<li> | |
<button id="run4">run with 4 threads</button> | |
<p id="result4"></p> | |
<p id="durations4"></p> | |
</li> | |
<li> | |
<button id="run8">run with 8 threads</button> | |
<p id="result8"></p> | |
<p id="durations8"></p> | |
</li> | |
</ul> | |
<script src="src.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Workerを1つ生成し、その終了イベントを監視するPromiseを生成して返す | |
const generatePromise = (worker, i, workers) => { | |
return new Promise((resolve, reject) => { | |
worker.onmessage = evt => { | |
resolve(evt.data) | |
} | |
worker.onerror = err => { | |
reject(err) | |
} | |
// Worker毎の負荷を平準化する | |
// (検査対象の数値が大きいほど重いので、前半後半のような分け方は不適当) | |
// (1ブロック=幅1000を交互に分担する) | |
// 例)Worker数3の場合: | |
// 0: 0- 999, 3000-3999, ... | |
// 1: 1000-1999, 4000-4999, ... | |
// 2: 2000-2999, 5000-5999, ... | |
worker.postMessage({ | |
order: i, | |
limit: 200000, | |
workers: workers.length, | |
stride: 1000 | |
}) | |
}) | |
} | |
// threads分のWorkerを生成して並列処理を実行する | |
const run = threads => { | |
const startTime = performance.now(); | |
const workers = [] | |
for (let i = 0; i < threads; i++) { | |
workers.push(new Worker('worker.js')) | |
} | |
// 実行 | |
const promises = workers.map(generatePromise) | |
Promise.all(promises) | |
.then(values => { | |
// サマリー | |
const duration = ((performance.now() - startTime) / 1000).toFixed(3) | |
const count = values.reduce((prev, cur) => prev + cur.count, 0) | |
$(`#result${threads}`).text(`${count} primes are found in ${duration} sec.`) | |
// Worker毎の結果 | |
const netDurations = values.map((value, i) => `${i}: ${value.duration.toFixed(3)}s`).join(', ') | |
$(`#durations${threads}`).text(netDurations) | |
}) | |
.catch(err => { | |
$(`#result${threads}`).text('an error occured. see console.') | |
console.error(err) | |
}) | |
} | |
// Worker数に応じた実行ボタンを生成、処理実行のハンドラを設定 | |
[1, 2, 4, 8].forEach(threads => { | |
$(`#run${threads}`).click(() => { | |
$(`#result${threads}`).text('running...') | |
run(threads) | |
}) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 並列化の効果を見たいだけなので、あえて効率の悪いアルゴリズムにしている | |
const judgePrimeByInefficientWay = n => { | |
if (n < 2) { | |
return false; | |
} | |
if (n === 2) { | |
return true; | |
} | |
for (let i = 2; i < n; i++) { | |
if (n % i === 0) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
// messageを受け取って処理開始 | |
self.addEventListener('message', (msg) => { | |
const startTime = performance.now() | |
let count = 0 | |
let i = msg.data.order * msg.data.stride | |
while(i < msg.data.limit) { | |
if (judgePrimeByInefficientWay(i)) { | |
count++ | |
} | |
i++ | |
if (i % msg.data.stride === 0) { | |
// 1ブロック分完了、次のブロックへ | |
i += msg.data.stride * (msg.data.workers - 1) | |
} | |
} | |
const duration = (performance.now() - startTime) / 1000 | |
// 呼び出し元にmessageを返す | |
self.postMessage({ | |
count, | |
duration | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment