Порахуйте частоту літер у текстах за допомогою паралельних обчислень.
Паралелізм полягає в тому, щоб виконувати паралельно те, що також можна виконати послідовно. Поширений приклад - підрахунок частоти літер. Застосуйте паралелізм, щоб обчислити загальну частоту кожної літери в масиві текстів.
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 Worker API. Як описує MDN:
Web Workers дають змогу виконувати операцію зі скриптом в окремому фоновому потоці, відмінному від головного потоку виконання застосунку.
З іншого боку, якщо JavaScript виконується в Node.js, який є цільовим середовищем виконання на Exercism, ця сама концепція має назву 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, щоб вивчати й опановувати JavaScript, а також 37 концепцій159 вправ та справжнє наставництво від людей, і все це безкоштовно.
Ми дослідимо різницю між конкурентністю і паралелізмом, розглянувши різні підходи, які застосовують такі мови, як JavaScript, Go, Elixir і Rust.