How does Object.observe/unobserve interact with garbage collection? - javascript

Does having an active Object.observe on an object prevent it from being garbage collected? Do you need to first call Object.unobserve to allow it to be garbage collected? Or does GCing an object remove all its active observers?

Observing an object does not keep it alive. Once the object dies, its observers simply won't receive any more events. At least that's true in V8's implementation, which is the only one so far. It's probably safe to assume that it will hold for other implementations as well, should this feature become standard some day.
However, observation keeps its active observers alive, plus some internal, heap-allocated data structures associated with each observer function. In fact, this additional data will only die when the function itself has also died, even if it has long ceased to observe anything.

Related

If I delete a document does it still need a recycle?

In Javascript I'm iterating through an array of UNIDs and getting a NotesDocument by UNID, then I do a doc.remove(true);
having done that is it necessary to do a doc.recycle()?
Short answer is yes.
For newbies, Notes objects in Java consist of a Java object and a reference to a C++ object. So when you a Java object becomes null (or useless), garbage collector will clear the memory space after a certain amount of time. However, the C++ handle will persist. So we are recycling notes objects to destroy C++ object references. This page has a good explanation abouyt recycling.
On the other hand, doc.remove() can be thought as a state change. Moreover, if soft deletion is enabled in your database, it won't even remove the document, will just mark as deleted (you have to call .removePermanently() to hard-delete it). The C++ object reference will stay in the memory.
Therefore, remove method will not trigger a recycle for the object. Recycle is only triggerred by the object itself or its parent.
I believe you should still recycle it. It's an object at that point not a document.

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.

If you want force garbage collection on a variable in Javascript, is it better to set it as null or undefined?

I am developing an Android game using JS framework. I want to make sure that some of the objects are garbage collected once I am done using them. How do i force it? Should I use null or undefined?
You can't force garbage collection (not in any sane fashion).
If your variables aren't going out of scope automatically, just set them to null.
Best advice is to define them in scope that makes them eligible for garbage collection. This means don't use global variables that never become eligible for collection. Instead declare them as locals.
You could set it to null, and if that is then the last reference to that object, it will become eligible for garbage collection.
http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
TGH's suggestion is the best though, I'd recommend that.
If you want force garbage collection on a variable in Javascript, is it better to set it as null or undefined?
Doesn't matter, you can even set it to another object you created: as long as the object originally referenced by the variable is no longer referenced anywhere, it can be garbage collected. Think of your object as "something being referenced by variables".
If no variables reference it, it can be garbage collected, and "putting another object into a variable" will make the variable no longer reference the previous object.
I want to make sure that some of the objects are garbage collected once I am done using them. How do i force it?
You can force major garbage collection to be triggered in a Node-based runtime (e.g. Electron or NW.js), by using the --expose-gc flag and running:
global.gc();
If your app/game is browser-based, in Chrome only you can use the --allow-natives-syntax switch (your users would need to pass this to Chrome themselves), and call:
%CollectGarbage();
Note: dead simple, but you might as well just do a window.location.reload() as a fallback, if you can easily continue from where you left off (e.g. reload the game into another level, if you will).
Remember, however, these calls won't screw around, and can block for whole seconds if there is a lot of garbage to collect. This can be ideal if you have determined pauses in your game, such as loading screens between levels, but tricky otherwise.
You might also want to consider using an object pool, with or without using manual garbage collection, to simply reduce garbage and improve performance.

How do you clear memory in Javascript?

var Obj = function(){}; var X = new Obj();
will X = null properly clear memory?
Also would this be equivalent?
var Obj = function(){};
var X = {};
X.obj = new Obj();
delete(X.obj);
EDIT
It would seem that although deleting X.obj would NOT immediately clear memory, it would help the garbage collection. If I don't delete X.obj, there would still be a pointer to an object and so the GC may not clean it up.
Although I'm picking #delnan's answer, if you're reading this you should def also catch Benubird's article.
I also notice I accidentally wrote delete(X) originally instead of delete(X.obj) - sorry.
The short answer is that you don't. delete simply removes a reference (and not in the way you try to use it, see the above link - delete is one of those language features few people actually understand), nothing more. The implementation clears memory for you, but it's not your business when (and even if, strictly speaking - this is why one shouldn't rely on finalizers in GC'd languages that offer them) it does. Note though:
Only objects that can be proven to be unreachable (i.e. no way to access it) to all code can be removed. What keeps references to whom is usually fairly obvious, as least conceptually. You just need to watch out when dealing with lots of closures, as they may capture more variables than you think. Also note that circular references are cleaned up properly.
There's a bug in old (but sadly still used) IE versions involving garbage collection of JS event handlers and DOM elements. Google (perhaps even SO) should have better material on my memory.
On the plus side, that means you won't get dangling pointer bugs or (save of course the aforementioned pitfalls) memory leaks.
No, that will not clear memory.
Read this:
http://perfectionkills.com/understanding-delete/
No - Javascript runs GC when it feels like it.
The Delete method only deletes the reference - not the object. Any other references would be left out in the open waiting for the garbage collector.
JavaScript has its own GC, and it will run around and clean things up when nothing refers to them anymore.
I still think it's a good practice to null objects.
Deleteing an object also helps the GC because it will see something dangling, and say "I'm going to eat you because you're all alone (and now some cynical laugh)".
You should look at Deleting Objects in JavaScript
Even though there's a GC, you still want to ensure your script is optimized for performance as peoples computers, browsers, and fricken toolbars (and the number of them), will vary.
Generally speaking, memory management in Javascript is user-agent-specific. The basics of the garbage collector are through reference-counting. So, by setting a reference to null (using the delete keyword or by explicit assignment), you can assure yourself that a reference will be cleaned up, IF the object does not have any references that will live outside of its creation scope. That being the case, the GC will have already cleaned up any objects or variables whose scope has ended without your explicitly setting it to null.
There are some things to take care of, though - circular references are easy to create in JS, especially between a DOM element and an object. Care must be taken to clear (or not create in the first place) references to and/or from DOM elements within objects. If you do create a to/from reference related to DOM, be sure to explicitly clean them up by setting the references to null - both on your object and on the DOM element. Simply setting a parent object to null is not sufficient if there are child objects with references to/from DOM or localStorage because those references will live on, and if there was any reference from the child to the parent, then the parent will live on in memory because of that reference.
Web pages can actually leak trash in your memory this way - after you navigate away, the circular references keep objects and DOM elements in memory until you've restarted the browser!
An article on the subject: http://docstore.mik.ua/orelly/webprog/jscript/ch11_03.htm, and another detailed look: http://blogs.msdn.com/b/ericlippert/archive/2003/09/17/53038.aspx
JavaScript memory is generally handled similarly to Java - I mean there is (or there should be) a garbage collector which would delete the object if there is no references to it. So yes, simply "nullifying " the reference is the only way you should "handle" freeing memory, and the real freeing is the JS host part.

Is it possible to retrieve an anonymous JavaScript object?

For example, I have this code:
{a: 42}
After this line was executed, I think the object is stored somehow in the memory, I'm wondering how can I get it, in some tricky way?
No.
You can't do this.
Any decent js interpreter will destroy it with the garbage collector.
No: once you lose all references to an object, you cannot recover it and the GC will collect it.
No.
Anonymous objects are intended to work this way. If you need to retrieve an object later on, you should simply name it. (I assume you are asking this question out of curiosity and not out of neccessity).
As soon as an object has no existing references to it, the garbage collector should destroy the object, as is confirmed by this page:
ECMAScript uses automatic garbage
collection. The specification does not
define the details, leaving that to
the implementers to sort out, and some
implementations are known to give a
very low priority to their garbage
collection operations. But the general
idea is that if an object becomes
un-referable (by having no remaining
references to it left accessible to
executing code) it becomes available
for garbage collection and will at
some future point be destroyed and any
resources it is consuming freed and
returned to the system for re-use.
This would normally be the case upon
exiting an execution context. The
scope chain structure, the
Activation/Variable object and any
objects created within the execution
context, including function objects,
would no longer be accessible and so
would become available for garbage
collection.

Categories