How to detect if an object has been garbage collected in Javascript? - javascript

I am building a JavaScript game that creates a Level object using var:
function start() {
var myGameLevel = new Level(2);
}
This Level object has a lot of functionality, primarily adding elements to the DOM and making them interactive. A simplification:
function Level(i) {
var _difficulty = i;
this.init = function(){
jQuery("#container").append(...game elements here...);
jQuery("#button").on('click', function() {...});
}
}
My question: How can I know if the Level object created in the start function has been garbage collected or not? I aim to use only var variables so that there are no external references. When the DOM is cleared of all game elements, I EXPECT the Level object to be released from memory, but how can I be sure?

Normally in JavaScript garbage collection is non deterministic. You cant know if or when an object is garbage collected. This applies to objects that are strong referenced.
In ES12 and after, you can use a FinalizationRegistry.
Finalizers lets you handle when an object is garbage collected, using a JavaScript callback. Still the limitation is that, when the callback will get executed is non deterministic. It may take a min or an hour.
// object creation
let abc = new Array(200).fill(true);
const cleanup = new FinalizationRegistry(key => {
// your code here
});
// tagging variable abc to finalizer
cleanup.register(abc, 'werwer');
// abc = null;

Weak references are considered a security risk, and thus not available to unprivileged code in browsers.
Those concerns don't apply to privileged code or serverside javascript execution, e.g. via node.js, and thus platform-specific weak reference implementations may be available to them.E.g. firefox addons can use Components.utils.getWeakReference()
For certain programming patterns WeakMap/WeakSet may be sufficient, but they do not allow the program to observe garbage collection because to do so it would need a key to probe those data structures, but holding onto that key would prevent the objects from being collected in the first place.
An additional concern voiced by JS implementors is that depending on how powerful a hypothetical weak ref APIs would be - e.g. offering finalization notifications - it could expose considerable amounts of GC behavior which in turn could constrain future implementations because changing behavior might break web applications.
Update: There now is a proposal to standardize weak references in JS that mitigates the perceived risks by tying the release of weakly reachable objects to the JS event loop, making the behavior more deterministic.
Update 2: The proposal has been implemented in various browsers as WeakRef

I dont think you can control JavaScript garbage collection.
Normally an variable or object can be collected if there are no references to it. So you can increase your chances of having an object collected by designing your logic to make the object go out of scope.

Related

How does the "creation phase" know how much memory space to set up?

In JavaScript: Understanding the Weird Parts the instructor explains that memory for variables is set up during a so-called creation phase (and that undefined is assigned); then the execution phase happens. But why is this useful when we don't know what value(s) the variable will later point to?
Clearly variables can point to many different things -from e.g. a short string all the way to a deeply nested object structure -and I assume that they can vary wildly in the amount of memory they need.
If line-by-line execution -including variable assignment -happens only in the later, execution phase, how can the initial creation phase know how to set up memory? Or, is memory set aside only for the name in each variable name/value pair, with memory for the value being managed differently?
The instructor is referring to Google Chrome's V8 engine (as is evidenced by his use of it in the video).
The V8 engine uses several optimization approaches in order to facilitate memory management. At first, it will compile the JavaScript code and during compilation it will determine how many variables (hidden classes, more later) it needs to create. These will determine the amount of memory originally allocated.
V8 compiles JavaScript source code directly into machine code when it is first executed. There are no intermediate byte codes, no interpreter. Property access is handled by inline cache code that may be patched with other machine instructions as V8 executes. 1
The first set is created by navigating the JavaScript code to determine how many different object "shapes" there are. Anything without a prototype is considered to be a "Transitioning object shape"
The main way objects are encoded is by separating the hidden class (description) from the object (content). When new objects are instantiated, they are created using the same initial hidden class as previous objects from the same constructor. As properties are added, objects transition from hidden class to hidden class, typically following previous transitions in the so-called “transition tree”. 2
Conversely, if the object does have a prototype then it will have its particular shape tracked separately.
Prototypes have 2 main phases: setup and use. Prototypes in the setup phase are encoded as dictionary objects. Any direct access to the prototype, or access through a prototype chain, will transition it to use state, making sure that all such accesses from now on are fast. 2
The compiler will essentially read all possible variables as being one of these two possible shapes and then allocate the amount of memory necessary to facilitate instantiating those shapes.
Once the first set of shapes is setup, V8 will then take advantage of what they call "fast property access" in order to build on the first set of variables (hidden classes) that were setup during the build.
To reduce the time required to access JavaScript properties V8 dynamically creates hidden classes behind the scenes 3
There are two advantages to using hidden classes: property access does not require a dictionary lookup, and they enable V8 to use the classic class-based optimization, inline caching 3
As a result, not all memory use is known during compilation, only how much to allocate for the core set of hidden classes. This allocation will grow as the code is executed, from things like assignment, inline cache misses, and conversion into dictionary mode (which happens when too many properties are assigned to an object, and several other nuanced factors).
1. Dynamic machine code generation, https://github.com/v8/v8/wiki/Design%20Elements#dynamic-machine-code-generation
2. Setting up prototypes in V8, https://medium.com/#tverwaes/setting-up-prototypes-in-v8-ec9c9491dfe2
3. Fast Property Access, https://github.com/v8/v8/wiki/Design%20Elements#fast-property-access
Javascript is a bit of a problem you know at least in my opinion
in Javascript there are specifications of the language made by ecmascript
and there are implementation made by developers
you have to understand that what is been taught about Javascript what's so called "under the hood" are the specifications of Javascript
you might have heard the terms Execution Context Lexical Environment.
They are only spec on how the language should work they give idea to the Developers how to build their JS engine in a way that it will behave like the spec.
An execution context is purely a specification mechanism and need not correspond to any particular artefact of an ECMAScript implementation. It is impossible for ECMAScript code to directly access or observe an execution context. ECMAScript
Every Javascript engine is implemented differently and they supposed to behave like the spec of ECMAScript
there is a concept that everytime when an execution context is created.
it has stages creation phase and execution phase.
everytime when creation phase begin it's allocating memory for the variables for that execution context.
in reality it doesn't work like that at all
there is no really a "Creation Phase" at least in V8 engine(Google Chrome JS Engine) in the way that you think.
i can give you a hint and tell you that eveytime when you call a function that
doesn't have another function inside it.
the variables inside that function are basically replacing some "block" in memory
i will give you a basic example let's say V8 engine uses some address in memory
let's say the address is 0x61FF1C
function setNum(){ var num = 5; }
everytime when i will call the setNum function the value for example of num will get stored at address 0x61FF1C EVERYTIME when i will call the function the value of num 5it will get stored at 0x61FF1C so it's overwriting the content that were before inside 0x61FF1C.
that's just how the v8 engine works in that scenario now the example i gave is just to get the idea i know it's sounds a little vague.
there is much more to the V8 engine which i'm not going to discuss because it's huge
by the way i'm not a V8 developer so i dont know everything about that engine
i'm not even close to that level but i know some things.
anyway i think that every JS Developer should think in the spec way but also remember that many engines behave like the spec but it doesn't mean that they work exactly like the spec
When any program executes, time of execution we call running time. During running time or processing time, processor process code and communicate with memory. Procesor takes code from memory, process it, result give back to memory, take other code. All the running time, some space in memory get grater; some space gets zero, some variables get the new value, some variables have been deleting, etc. Volume of working memory in running time is changing all the time.

can objects be marked not to be garbage collected?

I don't know too much about the JavaScript garbage collector, just that it attempts to manage references so that unreferenced objects can be periodically purged from memory. I was thinking about something that I thought might improve performance if it was feasible by the language implementers.
It would go something like this. In a file add a line:
"no gc";
This is similar to the use strict setting. It would mark everything defined in the file as not for garbage collection. I'm thinking this would be used in libraries like jQuery and underscore. All of the helper methods would be marked and stored in a separate area of memory that is not managed by the GC.
While I know this might end up keeping around stuff that is not ever used; it would at least isolate it from periodic GC process. So while we perhaps gobble up some extra memory, we at least lighten the load of GC processing.
I apologize for the naivety of this suggestion as I have never implemented GC. I am just wondering if this idea is feasible or if JavaScript somehow does this already.
if you want to keep them as cache then you have global scope.
In browser global scope is window,
hence consider if you dont want object X to never get garbage collected then simply you can write
window.nogc = X;
since window which is global scoped ,will be never garbage collected so its child references also wont be garbage colleted until we explicitly make it.
Garbage collection only runs when the thread is free. Nothing would be saved because GC only occurs when the system isn't busy.
So no, this isn't possible.
You can ensure that an object does not get collected by referencing it from a GC root, but not that it doesn't get processed by the GC.
The reason is that GC in JS VMs is usually implemented via Mark-and-Sweep, or a method that is functionally equivalent. The basic premise is that the GC goes through a cycle that goes like this:
The GC marks all objects in the heap as being "potentially available for release". This is usually done by a flag toggle which changes the interpretation of the existing marks on objects from meaning "need to keep" to "safe to release". So no actual iteration over the objects occurs at this stage. Telling the GC to "not mark" certain objects would actually require extra operations, not less.
The GC starts at the GC roots, and traverse through the reference tree, changing the mark of objects from "safe to release" to "need to keep". This is the "Mark" phase. GC roots can be global objects, the currently executing stack, pending callbacks on the event loop, etc. The tree-traversal itself can be done in various way as well, with DFS being the simplest.
The GC goes over all objects in the heap, and removes any that is still marked "safe to release". This is the "Sweep" phase. Many optimizations exist in this phase, which allows the GC to free memory used by a group of objects in a single operation. Nevertheless, this requires at least some level of iteration, over groups of objects, if not over objects themselves.
Now here's the issue with setting a "non-GC" arena: Suppose that an object in your "non-GC" arena was to reference a regular object. During the "Mark" phase, if that object is not marked, it would be released. That means that all of your "non-collectible" objects need to be GC roots in order to "keep" regular objects to which they refer. And being a GC root offers no performance advantage over being directly referenced by a GC root. Both must equally participate in the "Mark" phase.
The only alternative is for your non-collectible object to not be able to strongly reference collectible objects at all. This can be achieved by having your own binary heap, rather than using native JS objects. The binary data would not be interpreted as references, and the heap object would finish its marking phase in a single operation. This is what asm.js does: It preallocates a large array to act as its internal heap. To the VM, the entire array counts as one big object, and therefore no garbage collection is done on any data structures that are encoded within it. Using this method does have the flaw that you need to encode all of your objects and data structures into the heap's binary format, and decode them when you want to use them. When working with asm.js, this is handled by the compiler.
in JavaScript if you want to kill a object, you have to delete all the references.
let's say we have a object like this:
var myobj={ obj : {} };
and we want to GC the obj object, we have to do this:
myobj["obj"] = null;
delete myobj["obj"];
but if you define another variable referenced to that object, it won't be killed with those line. for instance if you do:
var obj = myobj.obj;
if you really want to delete the object, you have do the same for this variable:
obj = null;
delete obj;
then if there is no reference it would be killed.
in other word if you want to prevent your object from GC, create a reference some where and keep it private.

Renaming the 'this' keyword

I'm concerned that I might be using a code pattern that leaks memory. Here's a pseudocode example:
window.user = new User();
user.getBasicInfo(function(basicInfo){
user.name = basicInfo.name;
user.getDetailedInfo(function(detailedInfo){
user.favoriteColor = detailedInfo.favoriteColor;
});
});
In other words, I'm not using the 'this' keyword to refer to the user object; I'm referring directly to the user object stored within the window object.
Obviously, the JavaScript 'this' keyword has given lots of people lots of trouble. I've seen some people rename 'this' to make it more clear as they descend a scope chain:
window.user = new User();
user.getBasicInfo(function(basicInfo){
var userInOuterScope = this;
userInOuterScope.name = basicInfo.name;
userInOuterScope.getDetailedInfo(function(detailedInfo){
var userInInnerScope = this;
userInInnerScope.favoriteColor = detailedInfo.favoriteColor;
});
});
Not as pretty, but it seems like the scope chain might be less convoluted in that case.
Can the first approach leak memory? Can the second? To avoid leaking memory, must I pass everything as a parameter (and never refer to objects outside of the current scope)?
The potential to "leak memory" is not something relevant to the question you seem to be asking. That is, neither of the approaches have implications on memory use, at least not in any way clear to me.
The reason you might prefer to make use of the this facility in your code is that you might want a population of objects. In your case, you're apparently using the object as a singleton, so it makes no difference. However, that's really a special case, and you'd quickly find that it doesn't work so well if you've got 100 "User" objects.
Preserving the value of this (and it's not really "renaming" this; it's copying its value into another variable) inside a closure could result in a memory leak, or rather, could be part of a larger memory-leaking setup, but it's not problematic in and of itself. Making copies of object references is something that happens all the time.
edit — the "leakage" problem with closures comes about when a combination of things happens:
Some objects are referenced by variables in the closure scope (not weird or harmful in and of itself);
Functions with references to the closure scope "escape" from a function call, either by being returned or by being exported via global state side-effects (like registering an event handler) (also not weird or harmful in and of itself);
The population of these exported functions grow, or the functions themselves allocate more room when they're invoked and preserve references to the space allocated in the closure, or the exported functions end up directly referenced by DOM nodes (this is particularly a problem in IE).
Really, JavaScript doesn't have any unique problems with memory leaks that any language with real closures has. For a vast amount of actual JavaScript software in this world (utility code wired into web pages), it's pretty rare that memory leakage is a problem, I suspect, though the IE issue with DOM references has probably crashed a few browsers over the years (which probably hardly surprised the hapless users).
I don't like pushing frameworks on people, but it's definitely true that framework authors must worry about this stuff. Trusting in your framework to keep the DOM clean by making sure you only attach event handlers and data to the DOM via framework facilities is therefore a Good Idea.
It doesn't appear that you have any circular references in your code, so I wouldn't worry about memory leaks. You're not setting objects equal to other objects as far as I see ( http://jsfiddle.net/Akkuma/UTL3B/ as a quick example how it could lead to memory leaks).
Here are a few references on memory leaks
http://www.ibm.com/developerworks/web/library/wa-memleak/
http://www.javascriptkit.com/javatutors/closuresleak/index.shtml
http://javascript.crockford.com/memory/leak.html
Additionally, you can use Chrome's Heap Snapshot tool to be able to tell whether or not you are having memory leaks worth worrying about.
JavaScript's this is not the same this like Java's or C#'s. It represents the current context of something being executed.

in JavaScript, when finished with an object created via new ActiveXObject, do I need to set it to null?

In a Javascript program that runs within WSH and creates objects, let's say Scripting.FileSystemObject or any arbitrary COM object, do I need to set the variable to null when I'm finished with it? Eg, am I recommended to do this:
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fileStream = fso.openTextFile(filename);
fso = null; // recommended? necessary?
... use fileStream here ...
fileStream.Close();
fileStream = null; // recommended? necessary?
Is the effect different than just letting the vars go out of scope?
Assigning null to an object variable will decrement the reference counter so that the memory management system can discard the resource - as soon as it feels like it. The reference counter will be decremented automagically when the variable goes out of scope. So doing it manually is a waste of time in almost all cases.
In theory a function using a big object A in its first and another big object B in its second part could be more memory efficient if A is set to null in the middle. But as this does not force the mms to destroy A, the statement could still be a waste.
You may get circular references if you do some fancy class design. Then breaking the circle by hand may be necessary - but perhaps avoiding such loops in the first place would be better.
There are rumours about ancient database access objects with bugs that could be avoided by zapping variables. I wouldn't base my programming rules on such voodoo.
(There are tons of VBscript code on the internet that is full of "Set X = Nothing"; when asked, the authors tend to talk about 'habit' and other languages (C, C++))
Building on what Ekkehard.Horner has said...
Scripts like VBScript, JScript, and ASP are executed within an environment that manages memory for you. As such, explicitly setting an object reference to Null or Empty, does not necessarily remove it from memory...at least not right away. (In practice it's often nearly instantaneous, but in actuality the task is added to a queue within the environment that is executed at some later point in time.) In this regard, it's really much less useful than you might think.
In compiled code, it's important to clean up memory before a program (or section of code in some cases) ends so that any allocated memory is returned to the system. This prevents all kinds of problems. Outside of slowly running code, this is most important when a program exits. In scripting environments like ASP or WSH, memory management takes care of this cleanup automatically when a script exits. So all object references are set to null for you even if you don't do it explicitly yourself which makes the whole mess unnecessary in this instance.
As far as memory concerns during script execution, if you are building arrays or dictionary objects large enough to cause problems, you've either gone way beyond the scope of scripting or you've taken the wrong approach in your code. In other words, this should never happen in VBScript. In fact, the environment imposes limits to the sizes of arrays and dictionary objects in order to prevent these problems in the first place.
If you have long running scripts which use objects at the top/start, which are unneeded during the main process, setting these objects to null may free up memory sooner and won't do any harm. As mentioned by other posters, there may be little practical benefit.

Does JavaScript have a memory heap?

In other words, what options do I have to allocate memory in JavaScript?
I know you can allocate memory either globally, or inside function scope. Can I allocate memory dynamically? What does the new operator really mean?
Edit: here's a specific example. How would you implement reading an integer value from the user - n, and then read n integers into an array?
you can't allocate memory. you can create objects. that's what new does.
now, javascript is a queer creature: functions are also objects in javascript. So this mean that you can instantiate prettymuch everything using new.
So, the new operator means that a new object is being created.
Javascript also garbage-collects these variables, just like it happens in java. So if you know java, it should be easy for you to draw parallels.
cheers,
jrh
PS: when you allocate objects, you really are allocating memory. Only, you are not doing that explicitly. You can allocate an array, and make it behave like a memory buffer, but that will degrade javascript performance drastically: javascript arrays are not in-memory buffers, they are also objects (like everything else).
JavaScript has garbage collection and handles this for you.
However, you can help it by using the delete operator where appropriate.
From the Apple JavaScript Coding Guidelines:
Just as you used the new operator to
create an object, you should delete
objects when you are finished with
them, like this:
delete myObjectVariable;
The JavaScript runtime automatically
garbage collects objects when their
value is set to null. However, setting
an object to null doesn’t remove the
variable that references the object
from memory. Using delete ensures that
this memory is reclaimed in addition
to the memory used by the object
itself. (It is also easier to see
places where your allocations and
deallocations are unbalanced if you
explicitly call delete.)
Steve
Hmmm sounds to me like you are coming from the memory focused language and trying to shoe horn that logic into JS. Yes JS uses memory (of course), but we have garbage collection to take care of cleaning it all up.
If you are after specifics about the guts of memory allocation then you will have to hunt around for that. But as a rule thumb, when you use var, new or declaring a new function (or closure) you are gobbling up memory. You can get vars to null to flag them for garbage collection and you can use the delete keyword too although few do either of these unless they work Server-side (like myself with ASP JScript) where its important.
Javascript is really, really friendly — really, too friendly by half!
If you have an array of 3 elements, and you want to add a fourth, you can just act as if that array location already exists:
var arr = ['zero', 'one', 'two'];
// Now you have arr[0], arr[1] and arr[2].
// arr.length is equal to 3.
.
// to add arr[8]:
arr[8] = 'eight';
// Now you have arr[0] through arr[8]. arr.length is equal to 9.
// and arr[3] through arr[7] exist, and
// are initialized to undefined. (If I remember right.)
So being really specific with memory allocation is unnecessary when adding elelments.
No, you don’t need to and can’t allocate memory. The JavaScript interpreter does that automatically.
To answer the title of the question, if you are to trust in MDN, most JavaScript implementations have a heap:
Heap
Objects are allocated in a heap which is just a name to denote a large
mostly unstructured region of memory.
Several Runtimes Communicating Together
A web worker or a cross-origin iframe has its own stack, heap, and
message queue. Two distinct runtimes can only communicate through
sending messages via the postMessage method. This method adds a
message to the other runtime if the latter listens to message events.
For a deeper dive into memory management, there is also an article here although much of this is implementation specific.
You do not need to manually manage memory in Javascript. Both heap and stacks are used under the hood to manage memory and it depends on the implementation. Usually, local variables are on the stack and objects are on the heap.

Categories