Pro Yearly is on sale from $80 to $50! »

Understanding Memory Behavior on NodeJS

Understanding Memory Behavior on NodeJS

The idea is to talk about memory in nodejs (V8 behavior), describing common and more complex leaks. Presenting how to debug, detect and solve problems with memory.

Understanding concepts like heap/stack, mark-and-sweep, garbage, memory allocation, cyclic reference, memory life cycle, V8's stop-the-world and more. In addition to showing real cases of memory leaks from globo.com.

Ed35943d3199ea37b1b60c39615e8163?s=128

Raphael Amorim

September 29, 2017
Tweet

Transcript

  1. ~ Understanding Memory Behavior on NodeJS The memory concept in

    
 JavaScript engines @raphamundi
  2. Raphael Amorim This guy seems like a nice person, but

    he doesn’t. Seriously. He likes topics related to JavaScript, Python, Clojure, WebGL, Algorithms and sometimes force some git push. 
 Working most part of his time in useless globo.com • js foundation/jQuery member • Mozillian • Metido a besta • @raphamundi This guy seems like a he doesn’t. Seriously. related to JavaScript, WebGL, Algorithms and some git push. 
 Working most part of h open source projects. some git push. 
 Working most part of his open source projects.
  3. talentos.globo.com

  4. [Question] Would you board a plane programmed by JavaScript?

  5. [Question] Would you board a plane programmed by JavaScript? 54%

    Yes 32% No 14% I don’t know
  6. Motivations (?)

  7. Developers (not all) don’t considers (or just doesn’t know) how

    tricky can be memory management in Nodejs.
  8. INTRO

  9. Computer memory is any physical device capable of storing information

    temporarily or permanently.
  10. Computer memory is any physical device capable of storing information

    temporarily or permanently.
  11. the ‘ is 
 from 
 other ‼

  12. Memory is Limited

  13. NODEJS

  14. None
  15. Initially created for Google Chrome, but it can also be

    used as a standalone.
  16. 83%* of all INTERPRETERS AREN’T IN JAVASCRIPT *invented number

  17. None
  18. NodeJS is a C++ program controlled via V8 *https://github.com/v8/v8/wiki/Getting%20Started%20with%20Embedding

  19. Dynamic memory allocation

  20. Dynamic memory allocation Weakly typed

  21. Dynamic memory allocation Weakly typed "V8's stop-the-world"

  22. Dynamic memory allocation Weakly typed "V8's stop-the-world" "generational"

  23. V8: garbage collection

  24. Every program that consumes memory requires a mechanism for reserving

    and freeing space.
  25. In C and C++, this is accomplished by malloc() and

    free() Every program that consumes memory requires a mechanism for reserving and freeing space.
  26. char * buffer; buffer = (char*) malloc (42); // Do

    something with buffer free (buffer);
  27. char * buffer; buffer = (char*) malloc (42); // Do

    something with buffer free (buffer); What this means?
  28. In this case (C++) the programmer is responsible for freeing

    heap memory that is no longer required.
  29. Programmers make mistakes.

  30. /* Allocate 30 bytes to house a string */ char*

    str = new char [30]; /* Clear those 30 bytes and make str point nowhere */ delete [] str;
  31. /* Allocate 30 bytes to house a string */ char*

    str = new char [30]; /* Give str another memory address with the first one gone forever */ str = new char [60]; delete [] str;
  32. Fail to remove data that can not be referenced.

  33. When a portion of memory allocated for certain operation is

    not released when it's no longer needed.
  34. Fail to remove data that can not be referenced. When

    a portion of memory allocated for certain operation is not released when it is no longer needed. It’s a 
 Memory Leak
  35. Garbage collection is double-edged sword

  36. positive side: languages that use it become more simple.

  37. negative side: no control of memory.

  38. ECMAScript specification doesn't expose any interface to garbage collector.

  39. Performance of garbage collected languages is not strictly better or

    worse than languages without managed memory!
  40. V8: memory scheme

  41. Resident Set ~ V8 uses a scheme similar to the

    Java Virtual Machine and divides the memory into segments ~
  42. Resident Set Code Segment Stack Heap Used Heap

  43. ~Code Segment~ The actual code being executed

  44. [|||||] Stack Variable

  45. char *buff[500]

  46. Contains all value types with pointers referencing objects on the

    heap.
  47. [|||||] Heap Variable

  48. char *buff = (char *)malloc(500)

  49. A memory segment dedicated to storing reference types like objects,

    strings and closures.
  50. process.memoryUsage() *https://nodejs.org/api/process.html#process_process_memoryusage

  51. console.log(process.memoryUsage()); { rss: 4935680, heapTotal: 1826816, heapUsed: 650472, external: 49879

    }
  52. console.log(process.memoryUsage()); { rss: 4935680, heapTotal: 1826816, heapUsed: 650472, external: 49879

    } rss refer to resident set size.
  53. console.log(process.memoryUsage()); { rss: 4935680, heapTotal: 1826816, heapUsed: 650472, external: 49879

    } heapTotal and heapUsed refer to V8's memory usage.
  54. console.log(process.memoryUsage()); { rss: 4935680, heapTotal: 1826816, heapUsed: 650472, external: 49879

    } external refers to the memory usage of C++ objects bound to JavaScript objects managed by V8.
  55. Terms: generationals

  56. None
  57. How Memory Allocation works in Nodejs

  58. // allocation for Number var num = 42; // allocation

    for String var str = “my string”;
  59. // allocation for Number var num = 42; // allocation

    for String var str = “my string”; Rvalue Lvalue
  60. // each element is a not named reference var arr

    = [1, null, "ABC"]
  61. // each element is a not named reference var arr

    = [1, null, "ABC"] *In-Object slack tracking
  62. In-Object slack tracking

  63. // each element is a not named reference var arr

    = [1, null, "ABC"] *In-Object slack tracking *overflow array
  64. // callable - executable object function fun(a) { return a

    + 10 }
  65. // functions with expressions do object allocation myElement.addEventListener(‘click’, () =>

    {
 myElement.style.opacity = 0
 }, false)
  66. Cyclic reference

  67. // cycle allocation var a = {} var b =

    {} a.c = b b.d = a
  68. Hightlight: Garbage Collector Sample

  69. > var myObject = {
 person: { name: "raphael", age:

    21, }
 }
  70. var myObject = {
 person: { name: "raphael", age: 21,

    }
 } > var anotherObject = myObject
  71. var myObject = {
 person: { name: "raphael", age: 21,

    }
 } var anotherObject = myObject > myObject = 1
  72. > var yetAnotherObject = anotherObject.person person: { name: "raphael", age:

    21, }
 } var anotherObject = myObject myObject = 1
  73. > anotherObject = “some-random-string” var yetAnotherObject = anotherObject.person }
 }

    var anotherObject = myObject myObject = 1
  74. > yetAnotherObject = null anotherObject = “some-random-string” var yetAnotherObject =

    anotherObject.person var anotherObject = myObject myObject = 1
  75. Hightlight: Building A Leak

  76. easy, right?

  77. function LeakingClass() { // do-nothing }

  78. function LeakingClass() { // do-nothing } var leaks = []

  79. function LeakingClass() { // do-nothing } var leaks = []

    setInterval(function() { for (var i = 0; i < 100; i++) { leaks.push(new LeakingClass) } console.error('Leaks: %d', leaks.length) }, 1000)
  80. it’s so fun, let’s create another!

  81. const developer = { name: “amorim”, company: “globocom” } doWork(()

    => { const data = developer.name // doing a bunch of work })
  82. one more!

  83. const http = require(‘http') const server = http.createServer((req, res) =>

    { for (var i=0; i<1000; i++) { server.on('request', function LeakFunc() {}) } res.end(‘Hello, The Conf!’) }).listen(8585, ‘127.0.0.1') server.setMaxListeners(0) console.log(`Server running at 127.0.0.1:8585/. Process PID: ${process.pid}`)
  84. Hightlight: Debugging A Leak

  85. let’s get back to the leak examples

  86. function LeakingClass() { // do-nothing } var leaks = []

    setInterval(function() { for (var i = 0; i < 100; i++) { leaks.push(new LeakingClass) } console.error('Leaks: %d', leaks.length) }, 1000) leak.js
  87. node --inspect leak.js

  88. None
  89. None
  90. None
  91. Hint: You can also send the SIGUSR1 signal to an

    existing node process to enable the inspect mode as you need it.
  92. Hint2: It's important to use named constructors, otherwise the heap

    snapshots will not produce useful outputs for you.
  93. const http = require(‘http') const server = http.createServer((req, res) =>

    { for (var i=0; i<1000; i++) { server.on('request', function LeakFunc() {}) } res.end(‘Hello, The Conf!’) }).listen(8585, ‘127.0.0.1') server.setMaxListeners(0) console.log(`Server running at 127.0.0.1:8585/. Process PID: ${process.pid}`) server-leak.js
  94. npm i memwatch-next or npm i node-memwatch

  95. None
  96. › ab -n 1000 -c 100 http://127.0.0.1:8585/

  97. None
  98. None
  99. There’s a lot of tools to help you! - node-memwatch

    - node-heapdump - node-inspector - nodetime - v8-profiler - memwatch-next - ...
  100. const developer = { name: “amorim”, company: “globocom” } doWork(()

    => { const data = developer.name // doing a bunch of work }) closure-leak.js
  101. const developer = { name: “amorim”, company: “globocom” } doWork(()

    => { const data = developer.name // doing a bunch of work developer = null })
  102. Hightlight: Wrap up

  103. "Even valid code can cause memory leaks."

  104. theThing = null

  105. References: - https://blog.codeship.com/understanding-garbage- collection-in-node-js - https://speakerdeck.com/pantuza/memory-leak-em- javascript - https://medium.com/@_lrlna/garbage-collection-in-v8-an- illustrated-guide-d24a952ee3b8

    - http://jayconrod.com/posts/55/a-tour-of-v8-garbage- collection - https://github.com/v8/v8/wiki
  106. References: - https://stackoverflow.com/questions/19550253/memory- leaks-and-closures-in-javascript-when-and-why - https://www.nearform.com/blog/self-detect-memory-leak- node/ - https://github.com/felixge/node-memory-leak-tutorial -

    https://stackoverflow.com/questions/6261201/how-to- find-memory-leak-in-a-c-code-project
  107. Thank You @raphamundi