Node
¶Node
a single thread? ¶not truly, but it is a single thread in the sense that it has only one thread per process.
1const crypto = require('crypto')
2
3const start = Date.now()
4
5crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => {
6 console.log('1:', Date.now() - start);
7})
This is a simple example of Node
code that makes use of the crypto
module to hash a string.
when we run this code, it will take some time to execute, and then it will print out the time it took to execute the function.
till this moment doesn’t seem to be anything special, but if we run the same function again, we will see that it will take the same amount of time to execute the function.
1const crypto = require('crypto')
2
3const start = Date.now()
4
5crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => {
6 console.log('1:', Date.now() - start);
7})
8
9crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => {
10 console.log('2:', Date.now() - start);
11})
now we will see the two functions will take the same amount of time to execute, and this is because the thread pool.
thread pool is a set of threads that are available to execute tasks.
1const crypto = require('crypto')
2
3
4const start = Date.now()
5
6crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => {
7 console.log('1:', Date.now() - start);
8})
9
10crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => {
11 console.log('2:', Date.now() - start);
12})
13
14crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => {
15 console.log('3:', Date.now() - start);
16})
17
18crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => {
19 console.log('4:', Date.now() - start);
20})
21
22crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => {
23 console.log('5:', Date.now() - start);
24})
when we run this code, we will see that the first four functions will take the same amount of time to execute, and the fifth function will take a little bit longer to execute.
this is because the thread pool has only four threads by default, and the fifth function will wait for one of the threads to be available to execute it.
when we run the code, Node
will start up a thread pool with four threads by default, and these threads are available to execute code inside of our Node
application.
when we call crypto.pbkdf2
function, it will take the function and pass it off to one of the threads in the thread pool, and that thread will then execute the function.
when the function is done executing, it will then pass the result back to the Node
event loop, and then Node
will call the callback function that we passed to crypto.pbkdf2
function.
we can change the size of the thread pool by using process.env.UV_THREADPOOL_SIZE
environment variable.
1process.env.UV_THREADPOOL_SIZE = 2
if use windows, we can use set
command to set the environment variable when we run the code.
1set UV_THREADPOOL_SIZE=2 && node <filename>.js
now we will see that the first two functions will take the same amount of time to execute, and the third function will wait for one of the threads to be available to execute it.
Node
uses libuv
to handle the thread pool, and libuv
uses OS
delegation to handle the thread pool.
OS
delegation means that libuv
will delegate the task of creating threads to the OS
.
1const https = require('https');
2
3const start = Date.now();
4
5const doRequest = () => {
6 https.request('https://www.google.com', res => {
7 res.on('data', () => {})
8
9 res.on('end', () => {
10 console.log('time', Date.now() - start);
11 })
12 }).end()
13}
14
15doRequest()
16doRequest()
17doRequest()
18doRequest()
19doRequest()
20doRequest()
when we run this code, we will see all the requests will take the same amount of time to execute.
Libuv
Delegates the task of creating threads to the OS
, and the OS
will create threads to handle the requests.