Multithreading in Javascript

 


JavaScript is single-threaded, as you may realize. In other words, the event loop is handled by just one thread. Earlier browser versions shared a single thread between all tabs. By using process-per-site-instance or separate threads per tab, modern browsers have improved upon this. In spite of dedicated threads increasing the response time of webpages, they are not able to synchronize multiple scripts simultaneously on each tab.

Several scripts are running simultaneously, so why do we need them?

Because computers are so fast and each tab uses its own thread, webpages should run smoothly. As long as your browser does not perform a complex algorithm or render an intricate visualization, this is true for most cases. They slow down UI events and triggers by blocking the main thread. Thanks to Javascript’s introduction of its Web Workers in 2009, this problem was eased.

What exactly are Web Workers?

A Web Worker is a JavaScript script that is executed on a background thread apart from the main thread of execution. Messages are used to communicate between the main thread and workers. Using web workers to run process-intensive tasks in the browser without creating blocking instances is possible since they run on a separate thread to the main execution thread.

Nice, huh? Let’s build a few.

The process of spawning a Web Worker is pretty straightforward. Our first step is to create two files: the main file and the file in which the worker will execute its code. Because the web worker code needs to run in its own thread, separate files are required. We will call them main.js and worker.js. The Worker constructor takes the path of the worker file as its first argument:

// main.js
var worker = new Worker('worker.js');

Let’s send a message to our worker now that we have it. The worker object must be called using the postMessage() method.

// main.js
worker.postMessage('Happy Birthday');

A caveat about web workers is probably in order here. Workers and the main thread copy data, not exchange it. We should keep this in mind when deciding how much memory to allocate and how fast to transfer data.

Our worker will hear the ‘Happy Birthday’ message if the worker.js file is set to listen to the message event.

// worker.js
self.addEventListener('message', function(e) {
// code to be run
}

Worker files run code within the function blocks when they hear a message event. If you don’t want to return a variable, use a postMessage() function. It’s the same as any other normal function. With e.data, we can use the data from the sent message.

// worker.js
self.addEventListener('message', function(e) {
var message = e.data + 'to myself!';
self.postMessage(message);
}

We are sending the message ‘Happy Birthday to myself!’ in the above code.’ to the main execution thread. Consequently, we will also need a message event listener in the main file to receive the data and act upon it. Voicie la version finale de main.js :

// main.js
var worker = new Worker('worker.js');
worker.addEventListener('message', function(e) {
console.log(e.data);
}
worker.postMessage('Happy Birthday');

As an example, we will console.log ‘Happy Birthday to myself!’. If you can add the listener first, and then make sure the message is sent out last, it is logical to let us listen to the message before sending it out.

In our final step, we will close the worker thread by adding a function called self.close(). The final worker.js is as follows:

// worker.js
self.addEventListener('message', function(e) {
var message = e.data + 'to myself!';
self.postMessage(message);
self.close();
}

Let’s take a look at what just happened:

  1. In main.js, there is a web worker that runs code from worker.js
  2. An ‘Happy Birthday’ message is sent to the worker
  3. The worker, which had an event listener for ‘message’, received the message and executed the code within.
  4. The worker added ‘to myself!Adding the message ‘Happy Birthday to myself’ to the message data creates the message.Sends the data to main.js as a message
  5. There was another event listener within Main.js, which sent a message to console.log, saying ‘Happy Birthday to myself!’.

Simple!

As shown in the following code, n-queens are solved using web workers:

Index.html

<!DOCTYPE html>
<html>
<head>
<title>n-queens solver</title>
</head>
<body>
<script type="src/queenWorker.js"></script>
<script>
var num = parseInt(prompt("enter num"));
var all = (1 << num) - 1;
count = 0;
for (var i = 0; i < num; i++) {
var cols = 2 ** i;
var ld = 2 ** (i + 1);
var rd = 0;
if (i > 0) {
rd = 2 ** (i - 1);
}
var myWorker = new Worker('queenWorker.js');
myWorker.addEventListener('message', function(e) {
count += e.data;
console.log('worker count: ', e.data);
}, false);
myWorker.postMessage([ld, cols, rd, all]);
}
</script>
</body>
</html>

worker.js

self.addEventListener('message', function(e) {
let count = 0;
var findSolutions = function(ld, cols, rd, all) {
let poss = ~(ld | cols | rd) & all;
if (cols === all) {
count++;
}
while (poss) {
let negPoss = poss * -1;
let bit = poss & negPoss;
//let bit = poss & -poss;
poss = poss - bit;
findSolutions((ld | bit) << 1, cols | bit, (rd | bit) >> 1, all);
}
};
findSolutions(e.data[0], e.data[1], e.data[2], e.data[3]);
self.postMessage(count);
}, false);

Feel free to experiment! To test web workers, you cannot deploy them locally in Chrome due to security concerns. Please use Firefox instead.

*

Post a Comment (0)
Previous Post Next Post