I have few basic questions about dynamic object creation using Javascript.
I understand that browser takes care of allocating memory space for any 'new' keyword found in the JS. If my understanding is correct, then i have following queries one by one.
Query #1 : Please refer the comments given below for the two lines inside 'sample' function. That is my first query.
function sample() {
var a = 5; // is the memory allocated for variable 'a' in stack ?
var b = new obj1(); // The object instance created for 'obj1' gets allocated in heap?
}
var obj1 = function() {
this.strDate = "";
}
Query #2: Once the execution scope is out of function sample(), will the browser engine free the memory allocated for both the variables. I have read about GC's reference algorithm & mark and sweep algorithm
and recommendations to assign null to variables once not in use, yet could not get a clear cut idea on the standards to be followed as we would do in C++. If variable a is there in stack, then I need not worry
and if obj1 instance is no longer accessible or say unmarked or no further reference to it, will it also be cleared by GC ?.
Query #3: Do browsers differ in allocating and freeing memory for the instances created using 'new' operator. ( I had seen only about heap profilers in chrome and rather few more terms related to it, but I have also come across 'out of stack space' error. Does that mean all browsers would universally use both stack and heap ?
Please help me out here ;)
As a programmer, in JavaScript you do not have control over stack or heap allocation. You create objects or primitives that are located somewhere in the memory. Internally JS engines (such as V8 or Spidermonkey) perform all kinds of optimizations. Generally you can think of everything as if it's stored on heap.
To get started you need to know that GC frees the memory from the objects that are not referenced. While you hold a reference to an object somewhere in your code, it will not be destroyed.
Browsers (JS engines) do not leak memory allocation abstraction to you. The error you're referring to is probably call stack exceeded that happens when too many functions are called (mostly due to recursion).
Related
I have looked all over the internet and I can't seem to find an answer to this question.
I read that the stack is used to store primitives and heap is for objects.
I also read that the stack's size is fixed and once allocated it does not change, hence why it's used for primitives, because JS knows the size of each variable before runtime.
I also know that primitives are immutable, so if we try to reassign a variable, it will not change the value at its memory address but will rather allocate new space in memory, store the new value and assign its address to the variable.
If the above is correct, then what happens when I do this?
let string = "Hello World"; // Memory allocated for "Hello World"
string = string.ToUpperCase(); // New memory allocated for "HELLO WORLD"
Where does the new memory for HELLO WORLD get allocated? Is it in the stack because it's a primitive? Or is it in the heap because JS does not know its value until it runs the code?
If it's in the stack, what happens to the old "Hello World" then? Since only the heap is garbage collected does that mean that the old, unused, string will stay there until the program finishes running?
What happens if I do
string = string.repeat(10000000000)
If the stack can't grow, does it mean that at some point I can stack overflow because a variable is too large?
Thank you.
The answer may vary by engine, and it really doesn't matter to your code. Worry about running out of stack if/when you run out of stack. JavaScript's specification doesn't require implementations to do one thing or the other. It describes behavior, not the implementation of that behavior.
But speaking practically: It seems unlikely that a JavaScript engine would try to put a massive string on the stack. More likely, it would put it in the heap. That doesn't mean it can't put other strings on the stack. Maybe it decides based on size. Maybe it decides based on lifetime — perhaps it'll put a small string used only locally in a function on the stack, but put a massive one, or one retained globally, on the heap.
The point is: Modern JavaScript engines are complicated and highly, highly optimized. They're unlikely to take such a simplistic view as "primitives go on the stack and objects go on the heap."
I read that the stack is used to store primitives and heap is for objects.
Not necessarily. Objects can be allocated on the stack as well, and have been by at least some JavaScript engines at various points in history. If an object won't survive the end of the function call, and isn't massive, putting it on the stack makes reclaiming it when the function returns dead easy.
I also know that primitives are immutable, so if we try to reassign a variable, it will not change the value at its memory address but will rather allocate new space in memory, store the new value and assign its address to the variable.
Without getting too deep into theory, again this could well be implementation-specific. Consider a = 1. We have no way of telling whether that puts the value 1 in the memory associated with a, or puts a reference to an immutable singleton representing 1 in a. The former seems more a lot more likely than the latter (for numbers; strings are another matter), but we don't know and can't know (in the general case; we can for a specific version of a specific engine), because it makes no difference to our code and the spec doesn't require one behavior or the other.
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.
Do we need to unset variables in JavaScript, and why?
For example in PHP it's recommended to unset all temporary variables in all kind of loops to keep memory free and avoid variables duplicates.
But anyways according to php - what's the benefit of unsetting variables? question:
Is it true that unsetting variables doesn't actually decrease the memory consumption during runtime?
-Yep.
So should we delete window.some_var;?
Or we should use some_var = null?
Or we should not unset variables to avoid additional CPU cycles?
UPD:
Related questions:
How to unset a Javascript variable?
How to remove a property from a javascript object
No, plus in some cases you can't delete variables in the global scope. Variables that are properly declared using the var keyword cannot be deleted (implied global variables can be deleted, on the other hand. Always use the var keyword to declare variables).
Also, javascript engines have this thing called garbage collector that automatically looks for variables that are no longer used or referenced somewhere when your code is 'running'. Once it finds one, it'll shove it off immediately into the Abyss (deletes the variable in the memory)
No, it is not necessary to delete variables when you’re done with them. If you have so many enormous, global variables that this is actually a problem, you need to rethink your design.
And yes, it’s also silly in PHP, and no, it has nothing to do with avoiding “additional CPU cycles”.
Specifically:
“Unsetting temporary variables in loops”
They’re temporary, and probably either a) integers or b) references that take up about as much space as an integer. Don’t bother.
“Avoiding duplicate variables”
Again – references. Setting things that are still referenced elsewhere to null is pointless.
If you feel like it’s clutter, that is a good sign that more things should be going out of scope (i.e. use more functions).
In most other cases that you haven’t mentioned, the engine is also smart enough to manage your stuff properly. Do not optimize prematurely.
David Flanagan answers this quite nicely in his book, JavaScript: The Definitive Guide:
The JavaScript interpreter performs automatic garbage collection for memory management. This means that a program can create objects as needed, and the programmer never needs to worry about destruction or deallocation of those objects. When an object is no longer reachable – when a program no longer has any way to refer to it – the interpreter knows it can never be used again and automatically reclaims the memory it was occupying.
This doesn't mean that memory leaks can't happen in JavaScript. Far from it. Circular (or cyclic) references are a frequent problem in browsers which implement reference counting, as documented here by IBM:
A circular reference is formed when two objects reference each other, giving each object a reference count of 1. In a purely garbage collected system, a circular reference is not a problem: If neither of the objects involved is referenced by any other object, then both are garbage collected. In a reference counting system, however, neither of the objects can be destroyed, because the reference count never reaches zero. In a hybrid system, where both garbage collection and reference counting are being used, leaks occur because the system fails to identify a circular reference. In this case, neither the DOM object nor the JavaScript object is destroyed. Listing 1 shows a circular reference between a JavaScript object and a DOM object.
If you're worried that your website contains a JavaScript memory leak, Google has a tool, aptly named "Leak Finder for JavaScript", which can help you find the cause.
Further reading: What is JavaScript garbage collection?
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.
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.