JavaScript is often referred to as a high level single threaded garbage collected interpreted or just-in-time compiled prototype-based multi-paradigm Dynamic language with a non-blocking event Lube but what if we could change one of those words like single threaded to multi-threaded believe it or not we can actually do that thanks to workers in node.js and the web workers API in the browser in today's video I'll show you how to unlock massive performance gains by running multi-threaded JavaScript but before we do that let's talk about concurrency versus parallelism these terms sound similar and they're related but they're two very distinct Concepts normally JavaScript is a single threaded language which means it can only take advantage of one CPU core called the main thread however this one thread can execute code concurrently thanks to javascript's non-blocking event Loop for example when you have a time-consuming operation like a fetch call to an API that code gets executed off the main thread then when it completes it goes back to the main thread and executes a callback function a callback function is named that way for a reason it's literally like saying execute this code then call me back when you're done with concurrency you're doing multiple jobs that overlap over different time periods in no specific order it's kind of like a restaurant that only has one cook in the kitchen you might have something in the stove and in the oven and the microwave all at the same time but when it comes to Preparing a plate of food the chef can only handle one at a time but now let's talk about parallelism it's also all about doing things at the same time but instead it utilizes multiple CPU cores to run code that would otherwise block the main thread for the chef in the restaurant it's like having extra Cooks alongside him to prepare multiple plates of food at the same time in practice multi-threading is ideal when you have multiple CPU intensive jobs going at the same time like looping over a large array or processing a bunch of images at the same time would be CPU intensive what it's not very useful for though is i o intensive work like reading and writing to a database the file system or network communication because in those cases you're waiting for the disk or the network to supply the actual data and the CPU can't do a whole lot to speed that up so it's important to keep in mind that multi-threading doesn't just magically speed everything up it's just a way to distribute work across multiple CPU cores when the CPU is doing the heavy lifting his historically people have criticized JavaScript as a toy language in part because it was single threaded but it's actually been capable of multi-threading for many years there are libraries like Party Town that use web workers to run scripts in the background and that same API is also supported in Dino but what we're going to look at today is the workers API in node.js to follow along simply create an index.js file in your editor now before we get into workers I first want to simulate a CPU intensive task that would block the main thread let's imagine we have an array of jobs to simulate something that we need to compute in this case I'll just populate that array with the number one billion 100 times from there we'll create a nested for Loop that Loops over each one of those jobs then simply iterates from zero to one billion until it reaches the end totally pointless but it's good exercise for the CPU now let's go ahead and use the performance module to grab a timestamp before and after this code runs to measure the execution time now we can go ahead and open up the terminal run the node command and wait in my case it took over just 40 seconds to count to 100 billion and that's a lot faster than I could do it but not very impressive compared to a compiled language running on multiple threads however contrary to popular belief JavaScript is not slow when it's just in time compiled by V8 it actually performs way better than many other interpreted languages because V8 which is built with C plus compiles it to machine code before executing it performance will vary based on your machine and in my case I have an Intel I9 processor with eight physical cores but because it does hyper threading we technically have 16 cores to work with just a side note a core refers to the physical component of the CPU itself which can only execute one task at a time whereas a thread refers to a sequence of instructions that can be managed independently by the operating system scheduler there's a distinction to be made there but from a practical standpoint the amount of node.js workers you can run in parallel is equal to the available number of CPU cores which in this case is 16. now to keep this code organized I'm first going to create a new file called worker.js and we can simply move the loop that does the actual work into it the goal is to have the code in this file not run on the main thread we could actually combine all this code in a single file because the node worker module allows you to check if you're are actually on the main thread but I think it's a lot easier to reason about when you put your worker in a separate file and back in the main file I'll go ahead and import the worker class from the worker threads module then from there I'll create a function that takes the array of jobs as an argument and then also specify the number of concurrent workers or threads that we want to run in parallel from there I defined a helper function called chunkify that will take the initial array of jobs and then split it into an equal number of subarrays so that way each one of our workers is doing roughly the same amount of work like if we have a hundred jobs and four CPU cores each worker would get 25 jobs from there we can Loop over each one of those chunks and then instantiate a new worker by pointing it to the worker.js file that we just created now here's where things get interesting your workers can pass messages back and forth between the main thread after you instantiate a worker you'll need to pass the message telling it to get to work and that message can also include data which in this case would be a chunk of jobs from the initial array now let's go back into the worker file and see how we can receive that message by importing the parent port from the worker threads module we can receive that message from the main thread the message will contain the data we passed in from the main thread and allows us to execute a callback function to process that data on a completely separate thread which is automatically allocated by your machine now finally when the work is done you'll need to notify the main thread which is accomplished by calling post message with this method you can pass data back to the main thread or in this case we'll just simply tell it that we're done although you could just do process.exit here if you don't want to pass any data now the final step is to listen to messages on the main thread from the workers for each worker we'll set up a listener for the message at which point we'll know the worker has completed in real life though you'd likely want to collect the data from the worker and do something with it on the main thread you might also be wondering if threads can share data while they run and the answer is yes there's a channel called code with Ryan that has a great video about this called node.js is a serious thing now but I'm not going to get into it in this video because a long time ago I tried to synchronize data across threads in Python and I ended up with so many race conditions that the doctors had to amputate my leg but now it's time to find out if this showed results in any actual kind of performance gains the last thing I'll do here is use the node.js performance module to measure the amount of time it takes for all the workers to complete and now we're ready to fire up the V8 engine remember that first run on the main thread took 44 seconds so now let's go ahead and run two workers in parallel currently my CPU usage is at about five percent but that should change after we run this code we see a definite increase in utilization up to about 15 percent and then the total execution time was about 20 seconds roughly twice as fast as the initial run on the main thread and that's exactly what we would expect because we're now using two threads instead of one but now let's find out what happens when we give it some more juice with four workers as expected CPU usage goes up to about 30 percent and the execution time is Once Again cut in half to about 10 seconds let's go ahead and double it again to eight workers now this time CPU usage goes above 50 because that's half of our available threads and total execution time goes down to 6.2 seconds a definite increase but we're now starting to get some diminishing returns now finally let's go ahead and give it everything we've got with 16 work workers this time the CPU goes to 100 utilization and total execution time comes down to 4.7 seconds making it a total of 10 times faster than the initial run on the main thread now we could continue to add more workers like say a hundred but there will no longer be any increase in performance because there's no available CPU cores to use those threads everything on the entire machine is completely blocked now to finish up this video I want to show you a really cool trick related to threads while this video is playing right now go ahead and open up your browser Dev tools inside the console create a while loop with a condition of true and then inside the brackets just go ahead and do nothing I'll go ahead and give you a moment to do that because it's important to run this code while the video is playing remember the browser is also single threaded so when you run this code it will lock up the main thread and the page should become unresponsive and that means you'll be stuck on this video allowing me to achieve infinite watch time I can now tell you anything I want and you'll never be able to click away from this video [Music] and I'd like to take this opportunity to invite you to become a fireship pro member to learn how to do all kinds of other cool stuff with JavaScript thanks for watching and I will see you in the next one if you're still here that means your browser is probably Frozen and I apologize for that to fix it all you have to do is unplug your computer and then plug it right back in or you can right click on the browser Tab and close it because every tab has its own thread and if that doesn't work just leave me a comment below the video and I'll try to troubleshoot from there