I am currently building a game in Javascript. After some testing, I was beginning to notice occasional lag which could only be caused by the GC kicking in. II decided to run a profile on it. The result shows that the GC is in fact the culprit:
I read that creating new objects causes a lot of GC. I am wondering if something like this:
var x = [];
Creates any Garbage as well, since primitive types in Java don't do this. Since there are no real types in Javascript, I am unsure. Furthermore, which of these is the best for creating the least amount of garbage:
Option 1:
function do() {
var x = [];
...
}
Option 2:
var x = [];
function do() {
x = [];
...
}
Option 3:
function do() {
x = [];
...
}
Or Option 4:
function do() {
var x = [];
...
delete x;
}
Option 5:
var x = [];
function do() {
x.length = 0;
...
}
The do function is called 30 Times a Second in my case. And it runs several operations on the array.
I am wondering this, because I just made all of my variables global to try to prevent them from being collected by the GC, but the GC did not change much.
Could you also provide some common examples of things that create a lot of Garbage and some alternatives.
Thank you.
Can you also show the memory of timeline? If you have GC issues those should be blatantly obvious there as you would see a sawtooth wave graph. Whenever the graph drops, that's the GC kicking in, blocking your thread to empty our the trash and that's the main cause of memory related freezing
Example of sawtooth wave graph (the blue graph is memory):
Generally speaking, which object instantiation do you use does not matter than much since the memory impact of a [] is minimal, what you're interested in is the content of the arrays, but to go through your options:
Option 1: This is generally OK, with one consideration: Closures. You should try to avoid closures as much as possible since they're generally the main cause for GC.
Option 2: Avoid referencing things outside of your scope, it doesn't help memory-wise and it makes your app a bit slower since it has to go up the closure chain to find the match. No benefit to doing this
Option 3: never ever do this, you always want to define x somewhere otherwise you're purposely leaking into the global scope and therefore it will potentially never be GCed
Option 4: This is actually an interesting one. normally delete x does not do anything since delete only acts on properties of an object. In case you didn't know, delete actually returns a boolean that signifies whether the object has been deleted or not, so you can run this example in the chrome console:
function tmp () {
var a = 1;
delete a; // false
console.log('a=', a) // 1
b = 2;
delete b; // true !!!
console.log('b=', b) // Exception
}
tmp();
What the?! well when you say b = 2 (without the var) it's the same thing as writing window.b = 2 so when you're delete b, you're basically doing delete window.b which satisfy the "only delete property clause".
Still, DON'T DO THIS!
Option 5: This one actually saves you a tiny tiny bit of memory since it doesn't have to GC x, HOWEVER: it does have to GC all the content of x which is generally much greater in size that x itself therefore it won't make a difference
This is a fantastic article if you want to learn more about memory profiling + common memory performance pitfalls: http://www.smashingmagazine.com/2012/11/writing-fast-memory-efficient-javascript/
Related
I'm kind of curious about what the best practice is when referencing the 'global' namespace in javascript, which is merely a shortcut to the window object (or vice versia depending on how you look at it).
I want to know if:
var answer = Math.floor(value);
is better or worse than:
var answer = window.Math.floor(value);
Is one better or worse, even slightly, for performance, resource usage, or compatibility?
Does one have a slighter higher cost? (Something like an extra pointer or something)
Edit note: While I am a readability over performance nazi in most situations, in this case I am ignoring the differences in readability to focus solely on performance.
First of all, never compare things like these for performance reasons. Math.round is obviously easier on the eyes than window.Math.round, and you wouldn't see a noticeable performance increase by using one or the other. So don't obfuscate your code for very slight performance increases.
However, if you're just curious about which one is faster... I'm not sure how the global scope is looked up "under the hood", but I would guess that accessing window is just the same as accessing Math (window and Math live on the same level, as evidenced by window.window.window.Math.round working). Thus, accessing window.Math would be slower.
Also, the way variables are looked up, you would see a performance increase by doing var round = Math.round; and calling round(1.23), since all names are first looked up in the current local scope, then the scope above the current one, and so on, all the way up to the global scope. Every scope level adds a very slight overhead.
But again, don't do these optimizations unless you're sure they will make a noticeable difference. Readable, understandable code is important for it to work the way it should, now and in the future.
Here's a full profiling using Firebug:
<!DOCTYPE html>
<html>
<head>
<title>Benchmark scope lookup</title>
</head>
<body>
<script>
function bench_window_Math_round() {
for (var i = 0; i < 100000; i++) {
window.Math.round(1.23);
}
}
function bench_Math_round() {
for (var i = 0; i < 100000; i++) {
Math.round(1.23);
}
}
function bench_round() {
for (var i = 0, round = Math.round; i < 100000; i++) {
round(1.23);
}
}
console.log('Profiling will begin in 3 seconds...');
setTimeout(function () {
console.profile();
for (var i = 0; i < 10; i++) {
bench_window_Math_round();
bench_Math_round();
bench_round();
}
console.profileEnd();
}, 3000);
</script>
</body>
</html>
My results:
Time shows total for 100,000 * 10 calls, Avg/Min/Max show time for 100,000 calls.
Calls Percent Own Time Time Avg Min Max
bench_window_Math_round
10 86.36% 1114.73ms 1114.73ms 111.473ms 110.827ms 114.018ms
bench_Math_round
10 8.21% 106.04ms 106.04ms 10.604ms 10.252ms 13.446ms
bench_round
10 5.43% 70.08ms 70.08ms 7.008ms 6.884ms 7.092ms
As you can see, window.Math is a really bad idea. I guess accessing the global window object adds additional overhead. However, the difference between accessing the Math object from the global scope, and just accessing a local variable with a reference to the Math.round function isn't very great... Keep in mind that this is 100,000 calls, and the difference is only 3.6ms. Even with one million calls you'd only see a 36ms difference.
Things to think about with the above profiling code:
The functions are actually looked up from another scope, which adds overhead (barely noticable though, I tried importing the functions into the anonymous function).
The actual Math.round function adds overhead (I'm guessing about 6ms in 100,000 calls).
This can be an interest question if you want to know how the Scope Chain and the Identifier Resolution process works.
The scope chain is a list of objects that are searched when evaluating an identifier, those objects are not accessible by code, only its properties (identifiers) can be accessed.
At first, in global code, the scope chain is created and initialised to contain only the global object.
The subsequent objects in the chain are created when you enter in function execution context and by the with statement and catch clause, both also introduce objects into the chain.
For example:
// global code
var var1 = 1, var2 = 2;
(function () { // one
var var3 = 3;
(function () { // two
var var4 = 4;
with ({var5: 5}) { // three
alert(var1);
}
})();
})();
In the above code, the scope chain will contain different objects in different levels, for example, at the lowest level, within the with statement, if you use the var1 or var2 variables, the scope chain will contain 4 objects that will be needed to inspect in order to get that identifier: the one introduced by the with statement, the two functions, and finally the global object.
You also need to know that window is just a property that exists in the global object and it points to the global object itself. window is introduced by browsers, and in other environments often it isn't available.
In conclusion, when you use window, since it is just an identifier (is not a reserved word or anything like that) and it needs to pass all the resolution process in order to get the global object, window.Math needs an additional step that is made by the dot (.) property accessor.
JS performance differs widely from browser to browser.
My advice: benchmark it. Just put it in a for loop, let it run a few million times, and time it.... see what you get. Be sure to share your results!
(As you've said) Math.floor will probably just be a shortcut for window.Math (as window is a Javascript global object) in most Javascript implementations such as V8.
Spidermonkey and V8 will be so heavily optimised for common usage that it shouldn't be a concern.
For readability my preference would be to use Math.floor, the difference in speed will be so insignificant it's not worth worrying about ever. If you're doing a 100,000 floors it's probably time to switch that logic out of the client.
You may want to have a nose around the v8 source there's some interesting comments there about shaving nanoseconds off functions such as this int.Parse() one.
// Some people use parseInt instead of Math.floor. This
// optimization makes parseInt on a Smi 12 times faster (60ns
// vs 800ns). The following optimization makes parseInt on a
// non-Smi number 9 times faster (230ns vs 2070ns). Together
// they make parseInt on a string 1.4% slower (274ns vs 270ns).
As far as I understand JavaScript logic, everything you refer to as something is searched in the global variable scope. In browser implementations, the window object is the global object. Hence, when you are asking for window.Math you actually have to de-reference what window means, then get its properties and find Math there. If you simply ask for Math, the first place where it is sought, is the global object.
So, yes- calling Math.something will be faster than window.Math.something.
D. Crockeford talks about it in his lecture http://video.yahoo.com/watch/111593/1710507, as far as I recall, it's in the 3rd part of the video.
If Math.round() is being called in a local/function scope the interpreter is going to have to check first for a local var then in the global/window space. So in local scope my guess would be that window.Math.round() would be very slightly faster. This isn't assembly, or C or C++, so I wouldn't worry about which is faster for performance reasons, but if out of curiosity, sure, benchmark it.
Say we're writing a browser app where smooth animation is critical. We know garbage collection can block execution long enough to cause a perceptible freeze, so we need to minimize the amount of garbage we create. To minimize garbage, we need to avoid memory allocation while the main animation loop is running.
But that execution path is strewn with loops:
var i = things.length; while (i--) { /* stuff */ }
for (var i = 0, len = things.length; i < len; i++) { /* stuff */ }
And their var statements allocate memory can allocate memory that the garbage collector may remove, which we want to avoid.
So, what is a good strategy for writing loop constructs in JavaScript that avoid allocating memory each one? I'm looking for a general solution, with pros and cons listed.
Here are three ideas I've come up with:
1.) Declare "top-level" vars for index and length; reuse them everywhere
We could declare app.i and app.length at the top, and reuse them again and again:
app.i = things.length; while (app.i--) { /* stuff */ }
for (app.i = 0; app.i < app.length; app.i++) { /* stuff */ }
Pros: Simple enough to implement. Cons: Performance hit by dereferencing the properties might mean a Pyrrhic victory. Might accidentally misuse/clobber properties and cause bugs.
2.) If array length is known, don't loop -- unroll
We might be guaranteed that an array has a certain number of elements. If we do know what the length will be in advance, we could manually unwind the loop in our program:
doSomethingWithThing(things[0]);
doSomethingWithThing(things[1]);
doSomethingWithThing(things[2]);
Pros: Efficient. Cons: Rarely possible in practice. Ugly? Annoying to change?
3.) Leverage closures, via the factory pattern
Write a factory function that returns a 'looper', a function that performs an action on the elements of a collection (a la _.each). The looper keeps private reference to index and length variables in the closure that is created. The looper must reset i and length each time it's called.
function buildLooper() {
var i, length;
return function(collection, functionToPerformOnEach) { /* implement me */ };
}
app.each = buildLooper();
app.each(things, doSomethingWithThing);
Pros: More functional, more idiomatic? Cons: Function calls add overhead. Closure access has shown to be slower than object look-up.
And their var statements allocate memory can allocate memory that the garbage collector may remove, which we want to avoid.
This is slightly misinformed. Simply using var does not allocate memory on the heap. When a function is called, each variable used in the function is allocated in advance on the stack. When the function completes execution, the stack frame is popped and the memory is immediately dereferenced.
Where garbage collection-related memory concerns become a problem is when you're allocating objects on the heap. That means any of the following:
Closures
Event listeners
Arrays
Objects
For the most part, anything where typeof foo returns "function" or "object" (or any of the new ES6 typeof return values) will generate an object on the heap. There's probably more that I can't think of right now.
The thing about objects on the heap is that they can refer to other objects on the heap. So for instance:
var x = {};
x.y = {};
delete x;
In the example above, the browser simply can't deallocate the slot for x, because the value contained within it is of variable size. It lives on the heap, where it could then point to other objects (in this case, the object at x.y). Another possibility is that there's a second reference to the same object:
var x = {};
window.foo = x;
delete x;
The browser simply can't remove the object at x from memory, since something else is still pointed at it.
So long story short, don't worry about removing variables, because they work perfectly well and are totally performant. Heap allocations are the real enemy when it comes to garbage collection, but even a few small heap allocations here and there won't hurt most apps.
I've been reading up a lot on closures in Javascript. I come from a more traditional (C, C++, etc) background and understand call stacks and such, but I am having troubles with memory usage in Javascript. Here's a (simplified) test case I set up:
function updateLater(){
console.log('timer update');
var params = new Object();
for(var y=0; y<1000000; y++){
params[y] = {'test':y};
}
}
Alternatively, I've also tried using a closure:
function updateLaterClosure(){
return (function(){
console.log('timer update');
var params = new Object()
for(var y=0; y<1000000; y++)
{
params[y] = {'test':y};
}
});
}
Then, I set an interval to run the function...
setInterval(updateLater, 5000); // or var c = updateLaterClosure(); setInterval(c,5000);
The first time the timer runs, the Memory Usage jumps form 50MB to 75MB (according to Chrome's Task Manager). The second time it goes above 100MB. Occasionally it drops back down a little, but never below 75MB.
Check it out yourself: https://local.phazm.com:4435/Streamified/extension/branches/lib/test.html
Clearly, params is not being fully garbage collected, because the memory from the first timer call is not being freed... yet, neither is it adding 25MB of memory on EACH call, so it is not as if the garbage collection is NEVER happening... it almost seems as though one instance of "params" is always being kept around. I've tried setting up a sub-closure and other things... no dice.
What is MOST disturbing, though, is that the memory usage trends upwards. It might "just" be 75MB for now, but leave it running for long enough (overnight) and it'll get to 500 MB.
Ideas?
Thanks!
Allocating 25mb causes a GC to happen. This GC cleans up the last instance but of course not the current. So you always have one instance around.
GC does not happen when the program is idle. It does not happen between your timer calls so the memory stays around.
That is not even a closure. A closure is when you return something from a function, like an array, function, object or anything that can contain references, and it carries with it all the local members of that function.
what you have there is just a case of a very long loop that is building a very big object. and maybe your memory does not get reclaimed as fast as you are building the huge objects.
Once again I found JavaScript code on the Internet that contains an inline function where, in my opinion, regular statements would make just as much sense. Here's the first sample:
function outerHTML(node){
// if IE, Chrome take the internal method otherwise build one
return node.outerHTML || (
function(n) {
var div = document.createElement('div'), h;
div.appendChild(n.cloneNode(true));
h = div.innerHTML;
div = null;
return h;
})(node);
}
If you'd ask me to code the same thing, it would look like this:
function outerHTML(node){
var div, h;
// if IE, Chrome take the internal method otherwise build one
if (node.outerHTML) {
return node.outerHTML;
}
div = document.createElement('div')
div.appendChild(node.cloneNode(true));
h = div.innerHTML;
div = null;
return h;
}
EDIT: As OverZealous stated, there is a difference in logic on this one. I leave it here so nobody gets confused about that answer.
And maybe another original sample (yes, this doesn't "compile" as it's just a code fragment):
addGetters: function (attributes) {
var that = this;
function addGetter(attr) {
that.prototype["get" + attr.capitalize()] = function() { return this[attr]; };
}
for(var i = 0; i < attributes.length; i++) {
var attr = attributes[i];
addGetter(attr);
}
},
compared to my attempt
addGetters: function (attributes) {
for(var i = 0; i < attributes.length; i++) {
var attr = attributes[i];
this.prototype["get" + attr.capitalize()] = function() { return this[attr]; };
}
},
Is there a difference? Doesn't the original version consume more space since a function needs to be created and/or isn't it slower because of this? Is there a possible memory leak?
The utilisation of CPU and memory is very important as I'm coding in an environment where both are limited and any "less" is good. And since there's no sizeof() in JavaScript and its implementation attempts aren't safe to interpret any thinking-ahead-fixes are important.
Please note that as far as the "my version" is concerned I didn't test it. I'm just trying to explain what I'm trying to ask.
EDIT: Even though this question has an answer, I'm still wondering about the memory utilisation. If somebody has some insights, please don't hesitate to add it here.
For the first one, I don't believe there is any reason for the function. It might have (d)evolved into that state through small changes, but the extra function wrapper isn't providing any benefit that I can see.
The second example, however, is actually critical to use the function wrapper. The reason is due to JavaScript's (sometimes frustrating) function-level scope. In your example, there is only one attr variable. It is shared across the different attributes. This means that, in the end, every attribute will return the value of last attribute in the array.
e.g:
var attrs = ['foo', 'bar', 'baz']
obj.addGetters(attrs);
obj.getFoo(); // returns obj.baz
obj.getBar(); // returns obj.baz
By wrapping the getter creation in a function, you eliminate that issue, because attr ends up being scoped to the creating function. This is why Douglas Crockford's JSLint says "Don't create a function inside a loop". It leads to unexpected bugs like that one.
As OverZealous pointed out, one needs to be sure about the logic that's happening. +1 for that.
As far as the performance is concerned I finally had the time to do some testing on my own. However, I'm working in an environment where I can't really check memory utilisation. So I tried to fool around with the performance.
The result is that it may have an impact depending on how often this feature is used. On my target system the simple creation of an inline function that does close to nothing, e.g.
myArray.each(function inlineFunc(el) { return el; });
takes about 1.8 seconds for 10,000 creations of such a function (in the example above myArray had no elements). Just in comparison the PC-version of that browser needs 1,000,000 iterations to get somewhere close to that (obviously this also depends on the hardware).
Since the 10,000 iterations are reached in the code we use (not directly in one loop, but functions are created all over the code), we will have a word with our subcontractor.
The answer lies in the eye of the beholder.
It's a matter of preference.
It's up to you if you put "speed" above modularity.
Ask yourself this: why do you use a for when it can be done with a while? It is proven that in some cases the while structure is a bit faster.
I'm kind of curious about what the best practice is when referencing the 'global' namespace in javascript, which is merely a shortcut to the window object (or vice versia depending on how you look at it).
I want to know if:
var answer = Math.floor(value);
is better or worse than:
var answer = window.Math.floor(value);
Is one better or worse, even slightly, for performance, resource usage, or compatibility?
Does one have a slighter higher cost? (Something like an extra pointer or something)
Edit note: While I am a readability over performance nazi in most situations, in this case I am ignoring the differences in readability to focus solely on performance.
First of all, never compare things like these for performance reasons. Math.round is obviously easier on the eyes than window.Math.round, and you wouldn't see a noticeable performance increase by using one or the other. So don't obfuscate your code for very slight performance increases.
However, if you're just curious about which one is faster... I'm not sure how the global scope is looked up "under the hood", but I would guess that accessing window is just the same as accessing Math (window and Math live on the same level, as evidenced by window.window.window.Math.round working). Thus, accessing window.Math would be slower.
Also, the way variables are looked up, you would see a performance increase by doing var round = Math.round; and calling round(1.23), since all names are first looked up in the current local scope, then the scope above the current one, and so on, all the way up to the global scope. Every scope level adds a very slight overhead.
But again, don't do these optimizations unless you're sure they will make a noticeable difference. Readable, understandable code is important for it to work the way it should, now and in the future.
Here's a full profiling using Firebug:
<!DOCTYPE html>
<html>
<head>
<title>Benchmark scope lookup</title>
</head>
<body>
<script>
function bench_window_Math_round() {
for (var i = 0; i < 100000; i++) {
window.Math.round(1.23);
}
}
function bench_Math_round() {
for (var i = 0; i < 100000; i++) {
Math.round(1.23);
}
}
function bench_round() {
for (var i = 0, round = Math.round; i < 100000; i++) {
round(1.23);
}
}
console.log('Profiling will begin in 3 seconds...');
setTimeout(function () {
console.profile();
for (var i = 0; i < 10; i++) {
bench_window_Math_round();
bench_Math_round();
bench_round();
}
console.profileEnd();
}, 3000);
</script>
</body>
</html>
My results:
Time shows total for 100,000 * 10 calls, Avg/Min/Max show time for 100,000 calls.
Calls Percent Own Time Time Avg Min Max
bench_window_Math_round
10 86.36% 1114.73ms 1114.73ms 111.473ms 110.827ms 114.018ms
bench_Math_round
10 8.21% 106.04ms 106.04ms 10.604ms 10.252ms 13.446ms
bench_round
10 5.43% 70.08ms 70.08ms 7.008ms 6.884ms 7.092ms
As you can see, window.Math is a really bad idea. I guess accessing the global window object adds additional overhead. However, the difference between accessing the Math object from the global scope, and just accessing a local variable with a reference to the Math.round function isn't very great... Keep in mind that this is 100,000 calls, and the difference is only 3.6ms. Even with one million calls you'd only see a 36ms difference.
Things to think about with the above profiling code:
The functions are actually looked up from another scope, which adds overhead (barely noticable though, I tried importing the functions into the anonymous function).
The actual Math.round function adds overhead (I'm guessing about 6ms in 100,000 calls).
This can be an interest question if you want to know how the Scope Chain and the Identifier Resolution process works.
The scope chain is a list of objects that are searched when evaluating an identifier, those objects are not accessible by code, only its properties (identifiers) can be accessed.
At first, in global code, the scope chain is created and initialised to contain only the global object.
The subsequent objects in the chain are created when you enter in function execution context and by the with statement and catch clause, both also introduce objects into the chain.
For example:
// global code
var var1 = 1, var2 = 2;
(function () { // one
var var3 = 3;
(function () { // two
var var4 = 4;
with ({var5: 5}) { // three
alert(var1);
}
})();
})();
In the above code, the scope chain will contain different objects in different levels, for example, at the lowest level, within the with statement, if you use the var1 or var2 variables, the scope chain will contain 4 objects that will be needed to inspect in order to get that identifier: the one introduced by the with statement, the two functions, and finally the global object.
You also need to know that window is just a property that exists in the global object and it points to the global object itself. window is introduced by browsers, and in other environments often it isn't available.
In conclusion, when you use window, since it is just an identifier (is not a reserved word or anything like that) and it needs to pass all the resolution process in order to get the global object, window.Math needs an additional step that is made by the dot (.) property accessor.
JS performance differs widely from browser to browser.
My advice: benchmark it. Just put it in a for loop, let it run a few million times, and time it.... see what you get. Be sure to share your results!
(As you've said) Math.floor will probably just be a shortcut for window.Math (as window is a Javascript global object) in most Javascript implementations such as V8.
Spidermonkey and V8 will be so heavily optimised for common usage that it shouldn't be a concern.
For readability my preference would be to use Math.floor, the difference in speed will be so insignificant it's not worth worrying about ever. If you're doing a 100,000 floors it's probably time to switch that logic out of the client.
You may want to have a nose around the v8 source there's some interesting comments there about shaving nanoseconds off functions such as this int.Parse() one.
// Some people use parseInt instead of Math.floor. This
// optimization makes parseInt on a Smi 12 times faster (60ns
// vs 800ns). The following optimization makes parseInt on a
// non-Smi number 9 times faster (230ns vs 2070ns). Together
// they make parseInt on a string 1.4% slower (274ns vs 270ns).
As far as I understand JavaScript logic, everything you refer to as something is searched in the global variable scope. In browser implementations, the window object is the global object. Hence, when you are asking for window.Math you actually have to de-reference what window means, then get its properties and find Math there. If you simply ask for Math, the first place where it is sought, is the global object.
So, yes- calling Math.something will be faster than window.Math.something.
D. Crockeford talks about it in his lecture http://video.yahoo.com/watch/111593/1710507, as far as I recall, it's in the 3rd part of the video.
If Math.round() is being called in a local/function scope the interpreter is going to have to check first for a local var then in the global/window space. So in local scope my guess would be that window.Math.round() would be very slightly faster. This isn't assembly, or C or C++, so I wouldn't worry about which is faster for performance reasons, but if out of curiosity, sure, benchmark it.