-
The Internals of Node.jsFramework/Node.js 2020. 2. 21. 14:33
1. Overview
Node.js is an open-source, cross-platform, JavaScript library that executes JavaScript code outside of a browser. Node.js lets developers use JavaScript to write command-line tools and for server-side scripting—running scripts server-side to produce dynamic web page content before the page is sent to the user's web browser. Consequently, Node.js represents a "JavaScript everywhere" paradigm, unifying web application development around a single programming language, rather than different languages for server- and client-side scripts.
2. Description
2.1 Intuition
You want to write a javascript code and just have it work. So that's one of the purposes of node.js. Node gives us a nice interface to use to relate our javascript side of our application to the actual C++ that's running on our computer to actually interpret and execute our Javascript code.
So for example node implements the HTTP module and FS path crypto all these modules right here have very consistent API. And they all ultimately refer to a functionality that is mostly implemented inside of the lib project over here.
2.2 Module Implementation
V8 is used to interpret and execute Javascript code, while libuv is used for accessing the filesystem and some aspects of concurrency
3. Event Loop
3.1 Process and Threads
3.2 The Node Event Loop
This event loop is the absolute core of every program that you and I run and every program that you and I run has exactly one event loop. Understanding how the event loop works are extremely important because a lot of performance concerns about node boiled down to eventually how the event loop behaves.
3.2.1 Pseudo code of Event Loop
Pseudo Code of Event Loop of Node.js const pendingTimers = []; const pendingOSTasks = []; const pendingOperations = []; function shouldContinue() { // Check any pending setTimeout, setInterval, setImmediate // Check any pending OS tasks like server listening to port) // Check any pending long-running operations like fs module return pendingTimers.length || pendingOSTasks.length || pendingOperations.length } // Entire body execute while(shouldContinue()) { // 1) Node looks at pendingTimers and sees if any functions are ready to be called // setTimeout, setInterval // 2) Node looks at pendingOSTasks and pendingOperations and calls relevant callbacks // 3) Pause execution. Continue when... // - a new pendingOSTask is done // - a new pendingOperation is done // - a timer is about to complete // 4) Look at pendingTimers. Call any setImmediate // 5) Handle any 'close' events }
3.2.2 Single Thread or not
3.2.3 Thread example 1
const crypto = require('crypto'); // The instant we execute this file they are both executed at the same exact time. // The second thing to be aware of here is that we are not modifying the start variable at all. const start = Date.now(); crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => { console.log('1:', Date.now() - start); }); crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => { console.log('2:', Date.now() - start); }); // output of only one revoking pbkdf2 1: 473 // output of two revoking pbkdf2 // anyways the point is that chances are we're going to see two times or two benchmarks that are extremely // close in time to the original one. D:\nodejs>node threads.js 1: 455 2: 461
3.2.4 Thread example 2
const https = require('https') const start = Date.now() function doRequest() { https.request('https://www.google.com', res => { res.on('data', () => { }); res.on('end', () => { console.log(Date.now() - start); }); }).end(); } doRequest(); doRequest(); doRequest(); doRequest(); doRequest(); doRequest(); doRequest(); // output // This is distinctly different behavior than what we saw previously with our thread pool. // So remember by default the thread pool has four threads // which means only four task can be processed // at a time. // But in this case we had six tasks all completed simultaneously. D:\nodejs>node async.js 336 381 413 421 451 452 552
because libuv is delegating the work done to the operating system itself decides whether to make a new thread or not. Or just generally how to handle the entire process of making the request. So because the operating system is making the request there is no blocking of our javascript code inside of our event loop or anything else inside of our application. Everything or all the work is being done by the operating system itself and we're not touching a thread pool at all in this case.
3. Reference
https://heynode.com/tutorial/how-event-loop-works-nodejs
'Framework > Node.js' 카테고리의 다른 글
Data Caching with Redis (0) 2020.02.22 Enhancing Node Performance (0) 2020.02.21 Single Thread, Event Loop, and Blocking Code (0) 2020.02.21