Dissecting Node.js – Understanding the most famous JS runtime to the bare bone

Dissecting Node.js – Understanding the most famous JS runtime to the bare bone

0a8f40c6cc23fb6c8aad4de732c5abaf?s=128

Lucas Santos

April 04, 2020
Tweet

Transcript

  1. Dissecting Node.js Understanding the most popular JS runtime... To the

    bone
  2. whoami /khaosdoctor @_staticvoid lsantos.dev /khaosdoctor cloud advocate_ ludossan@microsoft.com

  3. obarra.co trainingcenter.io

  4. abcdevelopers.org

  5. agenda_ - What is JavaScript - What is Node.js -

    Our little function - How JavaScript works - V8 and its sorceries - V8 compiling pipelines - Putting it all together
  6. what is JavaScript?

  7. JavaScript The language everyone loves to hate - Prototype-based -

    Dynamically-typed - Interpreted language - Created in 1995 as a scripting language for Netscape - Created by Brendan Eich - Conforms with ECMA262 (ECMAScript) - Defined/Maintained by TC39
  8. what is Node.js?

  9. Node.js The angel that brought JS to the world again

    - JavaScript server-side runtime - Created in 2009 by Ryan Dahl - Later sponsored by Joyent - Event loop - Non blocking I/O - Uses V8
  10. None
  11. elements of Node.js_

  12. our little function_

  13. None
  14. fs is a C++ binding_

  15. None
  16. None
  17. the real Node.js_

  18. None
  19. None
  20. how JavaScript works?

  21. the JS engine_

  22. What is an engine? - Runs all JS code we

    write - Responsible for - parsing and interpreting - memory allocation - the call stack - garbage collection - code optimizations
  23. There are many - V8 -> made by Google for

    Chrome and some Chromium-based browsers - Chakra -> made by Microsoft for Microsoft Edge - SpiderMonkey -> made by Netscape, now runs on Firefox - Rhino -> made by Mozilla, in Java - Nitro -> made by Apple for Safari - JerryScript, Espruino -> IoT - And many others...
  24. Simplified diagram of an engine

  25. JavaScript is single-threaded_

  26. what means to be single-threaded? - We only have one

    call stack - We can only run one thing at a time
  27. call stack?

  28. call stack - Not part of JS - Provided by

    V8 - Data structure - Ordered as LIFO - Keeps track of function calls - Made of stack frames
  29. None
  30. Call Stack Step 0

  31. Call Stack Step 1 printSquare(5)

  32. Call Stack Step 2 printSquare(5) multiply(x, x)

  33. Call Stack Step 2 printSquare(5)

  34. Call Stack Step 3 printSquare(5) console.log(s)

  35. Call Stack Step 4 printSquare(5)

  36. Call Stack Step 5

  37. stack overflow

  38. Call Stack f() f() f() f() f() f() f() f()

    f()
  39. the hosting environment_

  40. hosting environment - Wherever place the code is running on

    - Provides external APIs - Handles async queues
  41. the real diagram

  42. event loop

  43. callbacks

  44. event loop - Handle async code - Puts queued callbacks

    onto the call stack - In Node, provided by libuv - Not part of V8 - Not part of JS
  45. libuv

  46. libuv more than an event loop - Open source -

    Created for node - Wrapper around libev - Provides - Event loop - TCP & UDP - DNS Resolution - FS Events - IPC and Child processes - Thread pool - More...
  47. None
  48. callback queues_

  49. None
  50. async callback function

  51. Call Stack Ext. APIs CB queue

  52. Call Stack Ext. APIs CB queue console.log('Starting')

  53. Call Stack Ext. APIs CB queue console.log('Starting') Starting

  54. Call Stack Ext. APIs CB queue

  55. Call Stack Ext. APIs CB queue fs.readFile(fp, cb)

  56. Call Stack Ext. APIs CB queue fs.readFile(fp, cb) file cb

  57. Call Stack Ext. APIs CB queue file cb

  58. Call Stack Ext. APIs CB queue file cb console.log('Ending')

  59. Call Stack Ext. APIs CB queue console.log('Ending') Starting Ending cb

  60. later does not mean "later"

  61. Call Stack Ext. APIs CB queue cb

  62. Call Stack Ext. APIs CB queue cb(err, data)

  63. Call Stack Ext. APIs CB queue cb(err, data) console.log(data.toS())

  64. Call Stack Ext. APIs CB queue Starting Ending The file

    contents cb(err, data) console.log(data.toS())
  65. Call Stack Ext. APIs CB queue cb(err, data)

  66. Call Stack Ext. APIs CB queue

  67. microtasks and macrotasks_

  68. microtask queue

  69. microtasks - process.nextTick - Promises - Object.observe

  70. macrotask queue

  71. macrotasks - setTimeout - setInterval - setImmediate - any I/O

    operation
  72. what would happen?

  73. Call Stack Ext. APIs CB queue Job queue console.log('start')

  74. Call Stack Ext. APIs CB queue Job queue console.log('start') start

  75. Call Stack Ext. APIs CB queue Job queue

  76. Call Stack Ext. APIs CB queue Job queue setTimeout('t1',0)

  77. Call Stack Ext. APIs CB queue Job queue setTimeout('t1',0) timer

    cb1
  78. Call Stack Ext. APIs CB queue Job queue timer cb1

  79. Call Stack Ext. APIs CB queue Job queue setTimeout('t2',0) timer

    cb1
  80. Call Stack Ext. APIs CB queue Job queue setTimeout('t2',0) timer

    cb1 timer cb2
  81. Call Stack Ext. APIs CB queue Job queue timer cb1

    timer cb2
  82. Call Stack Ext. APIs CB queue Job queue timer cb2

    .then(console.log) cb1
  83. Call Stack Ext. APIs CB queue Job queue handle setTimeout('t3',0)

    cb1 cb2
  84. Call Stack Ext. APIs CB queue Job queue timer cb3

    handle setTimeout('t3',0) cb1 cb2
  85. Call Stack Ext. APIs CB queue Job queue handle .then(fn)

    cb1 cb2 cb3
  86. Call Stack Ext. APIs CB queue Job queue handle .then(fn)

    fn cb1 cb2 cb3
  87. Call Stack Ext. APIs CB queue Job queue handle fn

    cb1 cb2 cb3
  88. Call Stack Ext. APIs CB queue Job queue handle fn

    cb1 cb2 cb3
  89. Call Stack Ext. APIs CB queue Job queue handle fn

    setTimeout('tp',0) cb1 cb2 cb3
  90. Call Stack Ext. APIs CB queue Job queue timer cb4

    handle fn setTimeout('tp',0) cb1 cb2 cb3
  91. Call Stack Ext. APIs CB queue Job queue timer cb4

    handle fn cb1 cb2 cb3
  92. Call Stack Ext. APIs CB queue Job queue timer cb4

    fn cb1 cb2 cb3
  93. Call Stack Ext. APIs CB queue Job queue fn cb1

    cb2 cb3 cb4
  94. Call Stack Ext. APIs CB queue Job queue fn console.log('promise')

    cb1 cb2 cb3 cb4
  95. Call Stack Ext. APIs CB queue Job queue fn console.log('promise')

    start promise cb1 cb2 cb3 cb4
  96. Call Stack Ext. APIs CB queue Job queue fn cb1

    cb2 cb3 cb4
  97. Call Stack Ext. APIs CB queue Job queue cb1 cb2

    cb3 cb4
  98. Call Stack Ext. APIs CB queue Job queue cb2 cb3

    cb4 cb1
  99. Call Stack Ext. APIs CB queue Job queue cb2 cb3

    cb4 cb1 console.log('timeout')
  100. Call Stack Ext. APIs CB queue Job queue cb2 cb3

    cb4 cb1 console.log('timeout') start promise timeout
  101. Call Stack Ext. APIs CB queue Job queue cb2 cb3

    cb4 cb1
  102. Call Stack Ext. APIs CB queue Job queue cb2 cb3

    cb4
  103. Call Stack Ext. APIs CB queue Job queue cb3 cb4

    cb2
  104. Call Stack Ext. APIs CB queue Job queue cb3 cb4

    cb2 console.log('timeout2')
  105. Call Stack Ext. APIs CB queue Job queue cb3 cb4

    cb2 console.log('timeout2') start promise timeout timeout2
  106. Call Stack Ext. APIs CB queue Job queue cb3 cb4

    cb2
  107. Call Stack Ext. APIs CB queue Job queue cb3 cb4

  108. Call Stack Ext. APIs CB queue Job queue cb4 cb3

  109. Call Stack Ext. APIs CB queue Job queue cb4 cb3

    console.log('timeout3')
  110. Call Stack Ext. APIs CB queue Job queue cb4 cb3

    console.log('timeout3') start promise timeout timeout2 timeout3
  111. Call Stack Ext. APIs CB queue Job queue cb4 cb3

  112. Call Stack Ext. APIs CB queue Job queue cb4

  113. Call Stack Ext. APIs CB queue Job queue cb4

  114. Call Stack Ext. APIs CB queue Job queue cb4 console.log('p

    timeout')
  115. Call Stack Ext. APIs CB queue Job queue cb4 console.log('p

    timeout') start promise timeout timeout2 timeout3 promise timeout
  116. Call Stack Ext. APIs CB queue Job queue cb4

  117. Call Stack Ext. APIs CB queue Job queue

  118. V8

  119. V8 the golden compiler - Made by Google - open

    source high-performance - JS and WebAsm engine - Written in C++ - Implements ES fully - Can be standalone
  120. abstract syntax tree_

  121. AST of readFile (part)

  122. hidden classes_

  123. None
  124. None
  125. None
  126. C2

  127. property order matters_

  128. V8 pipelines_

  129. AoT vs JiT

  130. old compiler pipeline_

  131. Full-Codegen

  132. FCG compiler fast, but not that good - First step

    of the pipeline - Simple and fast - Not-optimised, relatively slow - Handles type-feedback, finds hot functions - Takes the AST and generate generic native code
  133. Crankshaft

  134. Crankshaft compiler good, but not that fast - Takes type-feedback

    from FCG - Optimises code accordingly - Replaces not-opt code with optimised code using OSR - Does not implement all ES - Made of two components - Hydrogen - Lithium
  135. new compiler pipeline_

  136. new compiler pipeline

  137. TurboFan

  138. TurboFan Crankshaft, the right way - Started as a secondary

    compiler for ES6 - Designed to be a webasm compiler - Uses a sea of nodes - Receives bytecodes directly - Divided in layers - Frontend - Optimising Layer - Backend - Fixed deoptimisation cliffs
  139. mixed old pipeline

  140. current pipeline

  141. Ignition

  142. Ignition an interpreter to rule them all - JS Interpreter

    - Generates optimised bytecode - Created to reduce memory usage - Focused on low memory devices (cell phones) - NOT a parser - AST not source of truth anymore - Uses Turbofan's backend
  143. ignition pipeline_

  144. None
  145. bytecodes

  146. bytecodes are middle-class representations

  147. node --print-bytecode --print-bytecode-filter=f index.js

  148. putting it all together_

  149. None
  150. generated bytecode for readFileAsync

  151. Goes through this pipeline

  152. Call Stack Ext. APIs CB queue Job queue

  153. Call Stack Ext. APIs CB queue Job queue path.resolve

  154. Call Stack Ext. APIs CB queue Job queue

  155. Call Stack Ext. APIs CB queue Job queue IIFE

  156. Call Stack Ext. APIs CB queue Job queue IIFE readFileAsync

  157. Call Stack Ext. APIs CB queue Job queue handle IIFE

  158. Call Stack Ext. APIs CB queue Job queue handle

  159. Call Stack Ext. APIs CB queue Job queue handle

  160. Call Stack Ext. APIs CB queue Job queue handle readFile

  161. Call Stack Ext. APIs CB queue Job queue handle file

    cb
  162. Call Stack Ext. APIs CB queue Job queue cb

  163. Call Stack Ext. APIs CB queue Job queue cb

  164. Call Stack Ext. APIs CB queue Job queue cb resolve

  165. Call Stack Ext. APIs CB queue Job queue cb resolve

    callback
  166. Call Stack Ext. APIs CB queue Job queue cb resolve

    callback toString()
  167. Call Stack Ext. APIs CB queue Job queue cb resolve

    callback
  168. Call Stack Ext. APIs CB queue Job queue cb resolve

  169. Call Stack Ext. APIs CB queue Job queue cb

  170. Call Stack Ext. APIs CB queue Job queue cb console.log

  171. Call Stack Ext. APIs CB queue Job queue cb

  172. Call Stack Ext. APIs CB queue Job queue

  173. references_ - All references are in this guide: bit.ly/node-under-the-hood

  174. references_ - https://dev.to/khaosdoctor/node-js-under-the-hood-1-getting-to-know-our-tools-1465 - https://dev.to/khaosdoctor/node-js-under-the-hood-2-understanding-javascript-48cn - https://dev.to/khaosdoctor/node-js-under-the-hood-3-deep-dive-into-the-event-loop-135d - https://dev.to/khaosdoctor/node-js-under-the-hood-4-let-s-talk-about-v8-1eol -

    https://dev.to/khaosdoctor/node-js-under-the-hood-5-hidden-classes-variable-allocations-1244 - https://dev.to/khaosdoctor/node-js-under-the-hood-6-the-old-v8-34hm - https://dev.to/khaosdoctor/node-js-under-the-hood-7-the-new-v8-4gd6 - https://dev.to/khaosdoctor/node-js-under-the-hood-8-oh-the-bytecodes-1p6p - https://dev.to/khaosdoctor/node-js-under-the-hood-9-collecting-the-garbage-772
  175. thank you :D /khaosdoctor @_staticvoid lsantos.dev /khaosdoctor