Skip to content

Files

Latest commit

 

History

History
158 lines (104 loc) · 5.45 KB

memory.md

File metadata and controls

158 lines (104 loc) · 5.45 KB

Memory:

It is very important to understand how memory allocation is done, javascript automatically allocates memory when objects are created and frees it when they are not used anymore(garbage collection)


Memory life cycle:

  1. Allocate the memory you need.
  2. Use the allocated memory (read, write).
  3. Release the allocated memory when it is not needed anymore.

Primitive types memory size:

Type Size
undefined 0 bytes
boolean 4 bytes
number 8 bytes
string 2 bytes * number of characters

Example 16.0:

var num = 10; // allocates memory for number
var name = "Amr"; // allocates memory for string

var obj = {
  name: "Amr",
  job: "Software Engineer",
}; // allocates memory for object and contained values

var arr = ['a', 12]; // allocates memory for array and contained values

Garbage Collector(Release memory):

Garbage collector is responsible for figuring out when an allocated memory is not needed anymore and then releasing this allocated memory back to the OS, the process of figuring out if an allocated memory is not needed anymore is not easy, but the main key for this is references.

References

The main notion garbage collection algorithms rely on is the notion of reference. Within the context of memory management, an object is said to reference another object if the former has an access to the latter (either implicitly or explicitly). For instance, a JavaScript object has a reference to its prototype (implicit reference) and to its properties values (explicit reference).

Reference-counting garbage collection algorithm:

This is the most naive garbage collection algorithm. This algorithm reduces the definition of an object is not needed anymore to an object has no other objects referencing it. An object is considered garbage collectible if there are zero references pointing at this object.

Example 16.1:

var obj = {
  innerObj: {
    name: 'Amr',
  },
};
// { innerObj: { name: "Amr" }} has 1 reference => obj
// { name: "Amr" } has 1 reference => innerObj

// So far objects are still allocated in memory, none can be garbage-collected

var objNewRef = obj;
// { innerObj: { name: "Amr" }} has 2 references => obj + objNewRef
// { name: "Amr" } has 1 reference => innerObj

obj = 1;
// { innerObj: { name: "Amr" }} has 1 reference => objNewRef
// { name: "Amr" } has 1 reference => innerObj

var innerObjNewRef = objNewRef.innerObj;
// { innerObj: { name: "Amr" }} has 1 reference => objNewRef
// { name: "Amr" } has 2 reference => innerObj + innerObjNewRef

objNewRef = 1;

// { innerObj: { name: "Amr" }} has 0 reference => can be garbage collected
// { name: "Amr" } has 1 reference => innerObjNewRef

innerObjNewRef = 1;
// { name: "Amr" } has 0 reference => can be garbage collected

Limitation: cycles

There is a limitation when it comes to cycles. In the following example, two objects are created and reference one another, thus creating a cycle. They will go out of scope after the function call, so they are effectively useless and could be freed. However, the reference-counting algorithm considers that since each of the two objects is referenced at least once, neither can be garbage-collected.

Example 16.2:

function f() {
  var obj = {};
  var obj2 = {};
  obj.a = obj2; // obj references obj2
  obj2.a = obj; // obj2 references obj
}
f();

Mark and Sweep algorithm

This algorithm reduces the definition of an object is not needed anymore to an object is unreachable, this will fix cycles limitation.

This algorithm assumes the knowledge of a set of objects called roots (In JavaScript, the root is the global object). Periodically, the garbage-collector will start from these roots, find all objects that are referenced from these roots, then all objects referenced from these, etc. Starting from the roots, the garbage collector will thus find all reachable objects and collect all non-reachable objects, this is the used algorithm in all modern browsers.


Memory Leaks in javascript:

Memory leak happens when an allocated memory is not needed anymore, but the garbage collector was not able to determine that it is not needed as a result it will not be garbage collected.

Common memory leak mistakes

  1. Global Variables.
  2. Timers or callbacks that are forgotten.
  3. Closures.
  4. Out of DOM references.

1. Global variables:

In javascript using an undeclared variable will create a new variable in global object, in browser it will be created under window object

Example 16.3:

In this example we will see how initializing a variable without declaring it can cause an unintended leak.

function temp() {
  tempVar = 1; // this is equivalent to window.tempVar = 1;
}
temp(); // function execution is done but tempVar is still saved in global object and will never be released! Leak!

We can avoid this by adding use strict at the beginning of our javascript file, this will switch to strict mode in javascript execution and prevent such unintended global variables creation.

Example 16.4:

In this example we will see how incorrect usage of this can cause unintended global variables and as a result Leak.

function temp() {
  this.tempVar = 1;
}

temp(); // now `this` value inside temp function is equal to global window object, which will result in
// creating tempVar inside global window object. Leak!

2. Timers or callbacks that are forgotten