Node.js GC with unassigned function constructs - node.js

I know it's generally considered best practice in javascript to always assign a new function to a variable, even if it's not used. But in relation to garbage collection in node.js, is v8 able to GC functions that are not assigned to variables or does it make no difference?

As long as all references to a variable (anonymous or assigned) have been destroyed (in this case, by deallocation of the containing function) v8 should garbage collect it.

Related

Are NewGlobalRef / DeleteGlobalRef calls "recursive"?

A very basic question, but I don't see it explained anywhere in the docs. Say I have a jobject (or jclass). I create a global ref (NewGlobalRef) and store it for later use. Then I create another one and store it again. Then I delete the second ref, then I delete the first one. Will it work as I expected - ensuring the object is kept alive and all non-deleted references valid as long as the number of NewGlobalRef calls is greater than the number of DeleteGlobalRef calls for this object?
Yes.
Each JNI global and local reference is an individual garbage collection root. Roots refer to the first objects considered alive during a mark and sweep. An single object could have any number JNI references to it.
Of course, objects can reference other objects, so just because you delete all JNI references to an object doesn't mean it's no longer alive.
As for "recursive", I thought you meant something else. JNI references just reference heap objects and are not heap objects themselves. So, there is no recursion involved.
Some further reading at IBM's Overview of JNI object references.

Private variables memory allocation

Given a typical structure like the one below, when are the different variables being freed by the garbage collector?:
'Use strict';
var $ = require('jquery');
var somePrivateVar = new Whatever();
module.exports = functions (){
var someInsideVar = new Whatother();
var someOtherInsideVar = $('.myStuf');
$(window).scroll(function(){
somePrivateVar.MoreStuff();
doSomeStuff(someInsideVar);
someOtherInsideVar.toggle();
});
};
EDITED: the proposed another question is related but not the point of this question. I already know a little about garbage collection. I'm not interested in handling the garbage or avoiding it. I'm interested in how nodejs mounts the modules behind the scenes closure-wise. Put in other words, if you like, how nodejs implements those principles in the first response to the other question to handle efficiently the memory.
A module in node.js is simply a closure that stays alive by the same rules that other closures in Javascript would stay alive. As long as any code within the closure is still reachable by other code, then the closure itself can't be garbage collected. And, modules are also cached by the module loader which means a reference to the module is kept alive in the module cache, even if no other code has retained a reference to the module. You may find it helpful to read this article: How require() Actually Works because it is normal Javascript GC of a scope that determines when a given module can be garbage collected or not. There is no special garbage collection for modules.
So, your module variables will be alive as long as this module closure created when the module was loaded stays referenced. While that closure is alive, the only way that contents of the referenced variables within the module would be freed while the module was loaded is if you clear the contents of those variables manually (e.g. setting to null).
By default, a node module remains alive and loaded in the node module cache (waiting for some other code to require() it in again) even if it is no longer currently being used or referenced by the rest of your code. It can be manually removed from the cache if you so choose. See this answer for details on manually removing a module (and perhaps any modules that it also loads) from the cache: Unloading node code/modules. So, if none of your code has a reference to the module, the module has no live event handlers or callbacks in it and you've manually removed the module from the cache, then the module closure should no longer have any reachable code references into it and the GC can free that whole scope (and thus the module).
A module remains alive as long as any code in it is still reachable (e.g. can still be called by any other code). In your case, this would be the case if any other code still has a reference to the module or as long as the event handler in the module is still alive (could still be invoked) because the event handler callback references code within the module. It is not always clear exactly how smart a given garbage collector will be about knowing when a given event handler is done and can never be invoked again in the future.
In your specific example, the $(window).scroll() event handler (which seems like a bit of a made up example because there's usually no window object in node.js that does scrolling) would theoretically be alive forever until you manually removed the event handler with .off() or until the window object itself is deleted or something like that. So, the references inside that event handler would never go away on their own.
Other event handlers that have a specific lifetime such as an Ajax success handler will be done when the ajax call itself has finished executing and all callbacks have been called. Those event handlers will release any references they hold when they are done. Same for a setTimeout(). It will release any reference it holds when it executes (or when the timer is cancelled).
It is often times hard to predict how smart a garbage collector can be and when it will realize that a given variable is no longer reachable and thus can be garbage collected. Some things are easy to understand such as when a variable goes out of scope and no other references remain to the scope so the entire scope will be GCed. But some things are not so simple such as when a scope is still alive because an event handler in that scope is still alive, but nothing in that particular event handler could actually reference a given variable within that scope. Whether or not the GC will actually try to GC a single variable within that scope in that case is implementation dependent. Things like eval() and constructing new Function objects with code built via string manipulation make it very hard for Javascript to know exactly what could and could not be referenced in the future from a given event handler or callback (since it's possible to construct almost any reference programmatically without the interpreter knowing what you "may" reference in the future). This complicates fine grained garbage collection. What you can count on is whole scope garbage collection (when the whole scope is released). Counting on finer grained GC than that it probably not wise. If you are explicity done with a very large variable within a scope that might last a lot longer, then it's safer to just null out that very large variable so its specific reference to the large data is cleared when you want it to be cleared. This wouldn't be significant for a small string (unless you had tens of thousands of these objects), but might be relevant for a large buffer or very large string.
Edit: It does appear that V8 does garbage collection of individual variables within a scope if those variables themselves are not referenced within any of the code that is still reachable within the closure and there are no uses of eval() in that same code. I have not found any authoritative references on the subject, but have verified that this appears to be the case in testing actual situations.

How does Java garbage collector deals with circular references when their access path is broken?

I just want someone explain it to me that how does GC discover that those memory blocks (pictured in red area) are garbage when their reference count is more that 0 but they are practically inaccessible?
There's set of "root objects" which are considered always accessible: e.g., Thread references, static variables, class references. If some object can not be reached via link of references from these root objects, it considered to be available for GC, even if there are some references to that object.
GarbageCollector works based on Java Memory Model. In java available application memory is divided in two parts: Heap and Stack. A object is stored in heap memory and can be accessed by 2 ways :-
1) Object can have reference variable which is stored in stack memory. In this case object can be directly accessed by using it's reference variable.
2) Object can be contained by any other object and would not have any reference in stack memory. In this case this object can be accessed only by using that container object. So if container object is garbage collected then this object must be eligible for garbage collection.
While doing GarbageCollection GarbageCollector checks whether a object is accessible directly or indirectly by any reference available in stack if it is then it won't collect this object else it do collect it.
The details of the GC algorithm are implementation dependent in Java, so it depends on your VM. But most VMs do not use reference counting. The official VM even has several configurable algorithms available. So it is hard to generalize about this.

query regarding Garbage collector

i know GC release the memory of obj which is not used in any further but i know one thing that GC release memory in which form of like object or refrence or value....
please help me.
thanks in advance...
As a response to the comments to the question, it seems that you need clarification of a few concepts:
In .NET, objects live somewhere in the memory. A reference is kind of like a pointer to such an object/memory location. A value is some integral value (a number like 123).
For example, say you have an object of type MyClass, and you have created a new instance. This object contains a string. That string is another object, and your instance of MyClass holds a reference to the string object.
The garbage collector operates only on objects. It keeps track of the references to an object, if nobody is referencing the object any more the garbage collector can free that object up. In our example, if the garbage collector notices there's nobody holding a reference to the instance of MyClass, then it makes sure that object is freed. That in turn makes the reference to the string disappear, and the garbage collector can then also free the string (if nobody else is holding a reference, of course). Values don't need to be treated in any special way as they are part of the memory that belongs to an object (and thus cannot be freed "independently").
The same is true with Java, BTW.
An object of a reference type (a class) becomes garbage when no references to it exist anymore. It will be collected some time after that, whenever the GC runs next. The reason why these objects can be garbage is because they can be referenced from multiple places in the program, so no individual part of the program can release the object because other parts might still need it. The GC's responsibility is to discover when no part of the program needs the object anymore.
An object of a value type (a struct, or a built-in type like an integer) is simply copied to each place that needs to use it, so there's no problem of one value being used from multiple parts of the program. No GC is needed for value types, because they're always part of something else that ensures they're released. A value stored on the stack (e.g. a local variable within a method) is released when the method returns. A value stored in a class object is released when that class object becomes garbage.

How does the Garbage Collector decide when to kill objects held by WeakReferences?

I have an object, which I believe is held only by a WeakReference. I've traced its reference holders using SOS and SOSEX, and both confirm that this is the case (I'm not an SOS expert, so I could be wrong on this point).
The standard explanation of WeakReferences is that the GC ignores them when doing its sweeps. Nonetheless, my object survives an invocation to GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced).
Is it possible for an object that is only referenced with a WeakReference to survive that collection? Is there an even more thorough collection that I can force? Or, should I re-visit my belief that the only references to the object are weak?
Update and Conclusion
The root cause was that there was a reference on the stack that was locking the object. It is unclear why neither SOS nor SOSEX was showing that reference. User error is always a possibility.
In the course of diagnosing the root cause, I did do several experiments that demonstrated that WeakReferences to 2nd generation objects can stick around a surprisingly long time. However, a WRd 2nd gen object will not survive GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced).
As per wikipedia "An object referenced only by weak references is considered unreachable (or "weakly reachable") and so may be collected at any time. Weak references are used to avoid keeping memory referenced by unneeded objects"
I am not sure if your case is about weak references...
Try calling GC.WaitForPendingFinalizers() right after GC.Collect().
Another possible option: don't ever use a WeakReference for any purpose. In the wild, I've only ever seen them used as a mechanism for lowering an application's memory footprint (i.e. a form of caching). As the mighty MSDN says:
Avoid using weak references as an
automatic solution to memory
management problems. Instead, develop
an effective caching policy for
handling your application's objects.
I recommend you to check for the "other" references to the weakly referenced objects. Because, if there is another reference still alive, the objects won't be GCed.
Weakly referenced objects do get removed by garbage collection.
I've had the pleasure of debugging event systems where events were not getting fired... It turned out to be because the subscriber was only weakly referenced and so after some eventual random delay the GC would eventually collect it. At which point the UI stopped updating. :)
Yes it is possible. If the WeakReference is located in another generation than the one being collected, for example, if it is in the 2nd Generation, and the GC only does a Gen 0 collection; it will survive. It should not survive a full 2nd Gen collection that completes and where all finalizers run, however.

Resources