What Is JavaScript Garbage Collection

When and How JavaScript garbage collector works

V8 developer here. The short answer is: it's complicated. In particular, different JavaScript engines, and different versions of the same engine, will do things differently.

To address your specific questions:

a) When does Garbage collector kicks in ( it gets called after some interval or some conditions have to met) ?

Depends. Probably both. Modern garbage collectors often are generational: they have a relatively small "young generation", which gets collected whenever it is full. Additionally they have a much larger "old generation", where they typically do their work in many small steps, so as to never interrupt execution for too long. One common way to trigger such a small step is when N bytes (or objects) have been allocated since the last step. Another way, especially in modern tabbed browsers, is to trigger GC activity when a tab is inactive or in the background. There may well be additional triggers beyond these two.

b) Who is responsible for Garbage collection ( it's part of JavaScript engine or browser/Node ) ?

The garbage collector is part of the JavaScript engine. That said, it must have certain interactions with the respective embedder to deal with embedder-managed objects (e.g. DOM nodes) whose lifetime is tied to JavaScript objects in one way or another.

c) runs on main thread or separate thread ?

Depends. In a modern implementation, typically both: some work happens in the background (in one or more threads), some steps are more efficient to do on the main thread.

d) which one of the following have higher peak memory usage ?

These two snippets will (probably) have the same peak memory usage: neither of them ever lets objects allocated by more than one iteration be reachable at the same time.


Edit: if you want to read more about recent GC-related work that V8 has been doing, you can find a series of blog posts here: https://v8.dev/blog/tags/memory

What is JavaScript garbage collection?

Eric Lippert wrote a detailed blog post about this subject a while back (additionally comparing it to VBScript). More accurately, he wrote about JScript, which is Microsoft's own implementation of ECMAScript, although very similar to JavaScript. I would imagine that you can assume the vast majority of behaviour would be the same for the JavaScript engine of Internet Explorer. Of course, the implementation will vary from browser to browser, though I suspect you could take a number of the common principles and apply them to other browsers.

Quoted from that page:

JScript uses a nongenerational
mark-and-sweep garbage collector. It
works like this:

  • Every variable which is "in scope"
    is called a "scavenger". A scavenger
    may refer to a number, an object, a
    string, whatever. We maintain a list
    of scavengers -- variables are moved
    on to the scav list when they come
    into scope and off the scav list when
    they go out of scope.

  • Every now and then the garbage
    collector runs. First it puts a
    "mark" on every object, variable,
    string, etc – all the memory tracked
    by the GC. (JScript uses the VARIANT
    data structure internally and there
    are plenty of extra unused bits in
    that structure, so we just set one of
    them.)

  • Second, it clears the mark on the
    scavengers and the transitive closure
    of scavenger references. So if a
    scavenger object references a
    nonscavenger object then we clear the
    bits on the nonscavenger, and on
    everything that it refers to. (I am
    using the word "closure" in a
    different sense than in my earlier
    post.)

  • At this point we know that all the
    memory still marked is allocated
    memory which cannot be reached by any
    path from any in-scope variable. All
    of those objects are instructed to
    tear themselves down, which destroys
    any circular references.

The main purpose of garbage collection is to allow the programmer not to worry about memory management of the objects they create and use, though of course there's no avoiding it sometimes - it is always beneficial to have at least a rough idea of how garbage collection works.

Historical note: an earlier revision of the answer had an incorrect reference to the delete operator. In JavaScript the delete operator removes a property from an object, and is wholly different to delete in C/C++.

When is this scope/closure being garbage collected in javaScript?

Very briefly, garbage collection is a background process of the Javascript interpreter / virtual machine that automatically frees the memory of objects no longer needed by your program.

For example, since you think of it for event listeners: when you remove an event listener (a function usually) from some event dispatcher, it is likely that no other part of the program will have a reference to the event listener. Therefore, the garbage collector can and will (at some unknown time) free the memory that was taken by the event listener.

Since a closure references a scope object, in order to garbage-collect a closure it needs not only be unreferenced, but also the scope.

If I modify a bit your example:

/* some stuff ... */
function add10(a) {
var adder = function (x) {
return function(y) {
return x + y;
}
}

var sum = adder(10); //creates a closure
return sum(a);
}

var thirty = add10(20);

/* Some more stuff ... */

After add10 is called, even though the program continues to execute some more stuff, the garbage collector can free the memory associated to the closure sum, because it is no longer referenced, nor is the scope associated to it.

Whereas in this example:

/* some stuff ... */
function add10AndGet20Adder(a) {
var adders = function (x, y) {
return [function(z) {
return x + z;
}, function(z) {
return y + z;
}]
}

var sums = adders(10, 20); //creates a closure
return [sums[0](a), sums[1]];
}

var result = add10AndGet20Adder(50);
var sixty = result[0];
var add20 = result[1];

/* Some more stuff ... */

When executing some more stuff, sums[0] is no longer referenced, BUT add20 (sums[1]) still has a reference to the scope that references x andy, therefore none of the two closures in sums can be freed by the garbage collector, until add20 is referenced by the program.

I hope this makes it clearer, even though the examples are of course nowhere close to real code. In practice, you need to worry about this only if you develop a long-lived program (such as a single page application or nodeJS server) with complicated usage of closures. Otherwise, the memory usage of the closures is unlikely to be a problem.

This SO question gives more details about Javascript garbage collection: What is JavaScript garbage collection?

Are WebGL objects garbage collected?

Yes


From spec

Note that underlying GL object will be automatically marked for deletion when the JS object is destroyed


But you should notice that the object would probably not destroyed at the time you give up the last reference, so it's still a good practice to call deleteBuffer.

Javascript and Garbage collection

Javascript doesn't have explicit memory management, it's the browser which decides when to clean it up. Sometimes it may happen that you experience un-smooth rendering of JavaScript due to a garbage collection pause.

There are many techniques that you can apply to overcome glitches caused by garbage collection (GC). More you apply more you explore. Suppose you have a game written in JavaScript , and every second you are creating a new object then its obvious that at after certain amount of time GC will occur to make further space for your application.

For real time application like games, which requires lot of space the simplest thing you can do is to reuse the same memory. It depends on you how you structure your code. If it generates lots of garbage then it might give choppy experience.

By using simple procedures: This is well know that new keyword indicates allocation. Wherever possible you can try to reuse the same object by each time by adding or modifying properties. This is also called recycling of object

In case of Arrays, assigning [] is often used to clear array, but you should keep in mind that it also creates a new array and garbages the old one. To reuse the same block you should use arr.length = 0 This has the same effect but it reuses the same array object instead of creating new one.

In case of functions: Sometimes our program needed to call a specific function more time or on certain intervals by using setInterval or setTimeout.

ex: setTimeout(function() { doSomething() }, 10);

You can optimize the above code by assigning the function to a permanent variable rather than spawning each time at regular intervals.

    ex : var myfunc = function() { doSomething() }
setTimeout(myfunc, 10);

Other possible thing is that, the array slice() method returns a new array (based on a range in the original array,that can remain untouched), string's substr also returns a new string (based on a range of characters in the original string, that can remain untouched), and so on. Calling these functions creates garbage if not reutilized properly.

To avoid garbage completely in JavaScript is very difficult, you could say impossible. Its depends, how you reuse the objects and variables to avoid garbage. If your code is well structured and optimized you can minimize the overhead.

JavaScript - Garbage collection after function calls

Functions that don't contain a return statement implicitly return undefined. So a function "ending" and "returning" are the same thing.

Concerning garbage collection, keep in mind that local variables are not collected immediately after functions return; they can just become eligible for garbage collection at that point. The garbage collector runs whenever the browser considers it must run, or believes it can run without affecting visible performance much (and that's implementation-dependent).

Ensuring object can be garbage collected

Javascript uses a nongenerational mark-and-sweep garbage collector, in javascript objects are automatically garbage collected when they are no longer needed , so you need not worry about garbage collection.

but you have to keep these points in mind (from this answer):

  1. what you are trying with delete does not really delete an object, delete is only effective on an object's properties. It has no effect on variable or function names., Use delete statements whenever you create an object using a new statement, pair it with a delete statement. This ensures that all of the memory associated with the object, including its property name, is available for garbage collection. The delete statement is discussed more in “Freeing Objects.”

  2. Use the var keyword. Any variable created without the var keyword is created at the global scope and is never eligible for garbage collection, presenting the opportunity for a memory leak.

  3. In case of global variables, Global variables are never disposed of by the GC in the sense that a global variable will always exist. Setting it to null will allow the memory that it references to be collected. the memory used by the object will be eligible for collection. but The variable still exists though, and it simply references null(some more here)

How to Garbage Collect an external Javascript load?

Yes, it does benefit the GC to set the properties to null. Doing so removes the references from the element (that is contained in the DOM) to the handler function, and given that it probably is the only reference to the function it makes the function eligible for collection. However, unless the function is a closure over variables retaining a large block of memory, this is very unlikely to have a lot of impact.

You might also want to remove the s element from the DOM in the callback, making it garbage-collectable as well.



Related Topics



Leave a reply



Submit