並列計算を使って、テキストに含まれる文字の出現頻度を数えましょう。
並列処理とは、順番に実行することもできる物事を、並行して行うことです。よくある例が、文字の出現頻度を数えることです。並列処理を活用して、テキストの配列に含まれる各文字の出現頻度の合計を計算しましょう。
JavaScriptは本質的にシングルスレッドなので、並列なコード実行を扱うために他の言語が備えている言語機能の多くがありません。
実際のところ、「本当の」並列実行を実現する唯一の方法は、Worker threads(Web Workersとも呼ばれます)を使うことです。
並列に実行されているように見えるコード、たとえばasync functionsやPromisesなどは、ほとんどの場合、実際には並行して実行されているだけです。
現代のJavaScriptはそのような使い方に最適化されているため、多くの場合こちらの方が優れています。また、Promise.all()やその他の並行実行の手法を使って並列実行を「エミュレート」する(「ごまかす」)コードをよく目にするでしょう。
To pass the tests for this exercise, your solution needs to execute _concurrently_ (or in parallel),
meaning that synchronous solutions (e.g. a simple `for` loop) will not pass.
まずはそれぞれの簡単な定義を見て、両者の違いを確かめてみましょう。
念のため、同期実行の定義も挙げておきます。
JavaScriptはデフォルトではシングルスレッドですが、コードを並列に実行する方法はあります。
JavaScriptをブラウザで実行している場合(たとえばWebアプリなど)は、並列性を実現する方法はWeb Worker APIを使うことです。 MDNの説明は次のとおりです。
Web Workersを使うと、アプリケーションのメイン実行スレッドとは別のバックグラウンドスレッドでスクリプトの処理を実行できます。
一方、JavaScriptがExercismの実行環境であるNode.jsで動いている場合、同じ概念はWorker threadsと呼ばれます。
Be aware that the implementation of the worker API differs largely between browsers and other JavaScript environments.
Make sure to read the documentation for your specific runtime!
Web Worker APIの簡単なデモを紹介します(Mediumより)。
// main.js
const myWorker = new Worker('worker.js');
myWorker.postMessage(5);
myWorker.onmessage = function (event) {
console.log('Received result from worker:', event.data);
};
// worker.js
onmessage = function (event) {
console.log('Received number from main thread:', event.data);
// Perform computation
const result = event.data * 2;
// Send result back to the main thread
postMessage(result);
};
次はWorker threads APIのデモです(ドキュメントより)。
const {
Worker,
isMainThread,
parentPort,
workerData,
} = require('node:worker_threads');
if (isMainThread) {
module.exports = function parseJSAsync(script) {
return new Promise((resolve, reject) => {
const worker = new Worker(__filename, {
workerData: script,
});
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
});
});
};
} else {
const { parse } = require('some-js-parsing-library');
const script = workerData;
parentPort.postMessage(parse(script));
}
Currently it is not possible to implement parallelism using the online editor.
Please implement `Worker threads` using Node.js locally and submit your solution via CLI!
さらに挑戦したい場合は、自分の実装をWorker threadsを使うように応用できるか考えてみてください。
Exercismに登録すれば、37個のコンセプト159個の演習、そして本物の人間によるメンタリングとともに、JavaScriptを学んでマスターできます。すべて無料です。
並行性と並列性の違いを探りながら、JavaScript、Go、Elixir、Rustなどの言語が取るさまざまなアプローチを見ていきます。