Chapter 1: Why distributed? - Distributed Systems And Design NodeJS (copy)

0.0(0)
studied byStudied by 0 people
0.0(0)
full-widthCall with Kai
learnLearn
examPractice Test
spaced repetitionSpaced Repetition
heart puzzleMatch
flashcardsFlashcards
GameKnowt Play
Card Sorting

1/9

encourage image

There's no tags or description

Looks like no tags are added yet.

Study Analytics
Name
Mastery
Learn
Test
Matching
Spaced
Call with Kai

No study sessions yet.

10 Terms

1
New cards

JavaScript's Transition to Multithreading

JavaScript is evolving from a single-threaded to a multithreaded language. The Atomics object facilitates communication across different threads, while SharedArrayBuffer allows data to be read and written across threads. This transition enhances JavaScript's ability to handle concurrent operations efficiently.

2
New cards

Maximum Call Stack Size in JavaScript

The maximum call stack size in JavaScript is typically determined by the JavaScript engine.

The V8 JavaScript engine, which is used by Node.js v14, has a maximum call stack size of over 15,000 frames. This limit ensures that recursive functions and deeply nested calls can be handled efficiently without causing stack overflow errors.

3
New cards

How the Event Loop Manages Work in JavaScript

The event loop in JavaScript checks for more work to do only after the current call stack is complete. It does not check for new tasks after every single instruction. This design ensures that the event loop efficiently manages the execution of tasks, allowing the current stack to finish before moving on to the next set of tasks.

The event loop requires a nonzero amount of time to check for new tasks and prepare the new call stack. As a result, even though the function is scheduled to run in 0 milliseconds, it may take a few milliseconds to execute, especially as the application load increases.

<p>The event loop in JavaScript checks for more work to do only after the current call stack is complete. It does not check for new tasks after every single instruction. This design ensures that the event loop efficiently manages the execution of tasks, allowing the current stack to finish before moving on to the next set of tasks.</p><p>The event loop requires a nonzero amount of time to check for new tasks and prepare the new call stack. As a result, even though the function is scheduled to run in 0 milliseconds, it may take a few milliseconds to execute, especially as the application load increases.</p>
4
New cards

Message Passing in Isolated JavaScript Contexts

Since objects cannot be directly shared between different isolated JavaScript contexts, message passing is used to communicate. This involves sharing a serialized representation of an object or data (such as JSON) between the isolates.

Directly sharing objects is impossible and would lead to complex debugging issues like deadlocks and race conditions, where two separate isolates could modify the same object simultaneously. Message passing ensures safe and efficient communication between isolated contexts.

5
New cards

NodeJS Layers

  • libuv Thread Pool: Manages I/O operations and CPU-heavy tasks like cryptography and compression.

  • Finite Size: The thread pool has a limited number of threads, e.g., if there are four threads, only four files can be read simultaneously.

  • JavaScript Execution: While JavaScript code runs in the application, the underlying thread pool manages the I/O operations efficiently.

    Example Scenario: When an application reads a file, performs other tasks, and then processes the file content, a thread within Node.js handles reading the file from disk into memory.

<ul><li><p><strong>libuv Thread Pool</strong>: Manages I/O operations and CPU-heavy tasks like cryptography and compression.</p></li><li><p><strong>Finite Size</strong>: The thread pool has a limited number of threads, e.g., if there are four threads, only four files can be read simultaneously.</p></li><li><p><strong>JavaScript Execution</strong>: While JavaScript code runs in the application, the underlying thread pool manages the I/O operations efficiently.</p><p></p><p><strong>Example Scenario</strong>: When an application reads a file, performs other tasks, and then processes the file content, a thread within Node.js handles reading the file from disk into memory.</p></li></ul><p></p>
6
New cards

About Configuring libuv Thread Pool Size in Node.js

  • Default Size: The libuv thread pool size defaults to four threads.

  • Maximum Size: The maximum size is 1,024 threads.

  • Customization: The size can be overridden by setting the UV_THREADPOOL_SIZE=<threads> environment variable.

  • Practical Use: Modifying the thread pool size is uncommon and should only be done after thorough benchmarking in a production-like environment.

  • Environment Differences: An application running on a macOS laptop will behave differently than one in a container on a Linux server, highlighting the importance of environment-specific testing.

7
New cards

The Event Loop Phases of NodeJS

The order of the event loop in Node.js is similar to that in the browser, but with some additional phases specific to Node.js. In NodeJS, each one of the phases maintains a queue of callbacks that are to be executed. Callbacks are destined for different phases based on how they are used by the application.

  • Poll: Executes I/O-related callbacks. This is the phase where most applications’ code runs.

  • Check: Executes callbacks triggered by setImmediate().

  • Close: Executes callbacks triggered by EventEmitter close events, such as when a net.Server TCP server closes.

  • Timers: Executes callbacks scheduled by setTimeout() and setInterval().

  • Pending Callbacks Phase: Executes I/O callbacks that were deferred to the next loop iteration. These are callbacks for operations that were not completed in the previous iteration of the event loop and need to be handled in the next cycle, such as reading files or other asynchronous operations.

These phases ensure that different types of callbacks are handled efficiently within the Node.js event loop.

(25-29)

<p>The order of the event loop in Node.js is similar to that in the browser, but with some additional phases specific to Node.js. In NodeJS, each one of the phases maintains a queue of callbacks that are to be executed. Callbacks are destined for different phases based on how they are used by the application.</p><ul><li><p><strong>Poll</strong>: Executes I/O-related callbacks. This is the phase where most applications’ code runs.</p></li><li><p><strong>Check</strong>: Executes callbacks triggered by <code>setImmediate()</code>.</p></li><li><p><strong>Close</strong>: Executes callbacks triggered by <code>EventEmitter</code> close events, such as when a <code>net.Server</code> TCP server closes.</p></li><li><p><strong>Timers</strong>: Executes callbacks scheduled by <code>setTimeout()</code> and <code>setInterval()</code>.</p></li><li><p><strong>Pending Callbacks Phase</strong>: Executes I/O callbacks that were deferred to the next loop iteration. These are callbacks for operations that were not completed in the previous iteration of the event loop and need to be handled in the next cycle, such as reading files or other asynchronous operations.</p></li></ul><p>These phases ensure that different types of callbacks are handled efficiently within the Node.js event loop.</p><p>(25-29)</p>
8
New cards

The order of execution of the NodeJS event loop

  1. The script starts off executing line by line in the Poll Phase.

    1. Next Tick Queue: This queue is for callbacks scheduled using process.nextTick(). These callbacks are given the highest priority and are executed before any other microtasks.

    2. Microtask Queue: This queue is for other microtasks, such as those created by promises. These microtasks are executed after the next tick queue has been processed.

  2. Check Phase: Executes callbacks triggered by setImmediate().

  3. The Close Phase: Executes callbacks triggered by EventEmitter close events, such as when a net.Server TCP server closes.

  4. Timers: Executes callbacks scheduled by setTimeout() and setInterval().

  5. Pending Phase: the event loop continues back around to the poll phase. If nothing in the poll phase, it exits.

<ol><li><p><strong>The script starts off executing line by line in the <u>Poll Phase.</u></strong></p><ol><li><p><strong>Next Tick Queue</strong>: This queue is for callbacks scheduled using <code>process.nextTick()</code>. These callbacks are given the highest priority and are executed before any other microtasks.</p></li><li><p><strong>Microtask Queue</strong>: This queue is for other microtasks, such as those created by promises. These microtasks are executed after the next tick queue has been processed.</p></li></ol></li><li><p><strong>Check Phase: </strong>Executes callbacks triggered by <code>setImmediate()</code>.</p></li><li><p><strong>The Close Phase: </strong>Executes callbacks triggered by <code>EventEmitter</code> close events, such as when a <code>net.Server</code> TCP server closes.</p></li><li><p><strong>Timers</strong>: Executes callbacks scheduled by <code>setTimeout()</code> and <code>setInterval()</code>.</p></li><li><p><strong>Pending Phase</strong>: the event loop continues back around to the poll phase. If nothing in the poll phase, it exits.</p></li></ol><p></p>
9
New cards
10
New cards

Event Loop Tips

  • Don’t starve the event loop: void blocking the event loop with long-running tasks. Break tasks into smaller chunks and use asynchronous functions to keep the event loop responsive. For example, if you need to process 1,000 data records, you might consider breaking it up into 10 batches of 100 records, using setImmediate() at the end of each batch to continue processing the next batch. Depending on the situation, it might make more sense to offload processing to a child process.

  • Don’t introduce Zalgo: This tip warns against writing functions that can behave both synchronously and asynchronously. Such functions can lead to unpredictable behavior and make your code harder to debug. To avoid introducing Zalgo, ensure that your functions are consistently asynchronous, even if they execute immediately. You can use techniques like process.nextTick or setTimeout to always invoke callbacks asynchronously.

(30-31)