I'm making a pretty simple game just for fun/practice but I still want to code it well regardless of how simple it is now, in case I want to come back to it and just to learn
So, in that context, my question is:
How much overhead is involved in object allocation? And how well does the interpreter already optimize this? I'm going to be repeatedly checking object grid positions, and if they are still in the same grid square, then no updating the grid array
if (obj.gridPos==obj.getCurrentGridPos()){
//etc
}
But, should I keep an outer "work" point object that the getCurrentGridPos() changes each time or should it return a new point object each time?
Basically, even if the overhead of creating a point object isnt all that much to matter in this scenario, which is faster?
EDIT:
this? which will get called every object each frame
function getGridPos(x,y){
return new Point(Math.ceil(x/25),Math.ceil(y/25));
}
or
//outside the frame by frame update function looping through every object each frame
tempPoint= new Point()
//and each object each frame calls this, passing in tempPoint and checking that value
function makeGridPos(pt,x,y){
pt.x = Math.ceil(x/25);
pt.y = Math.ceil(y/25);
}
Between your two code examples that you have now added, I know of no case where the first would be more efficient than the second. So, if you're trying to optimize for performance or memory use, then re-using an existing object will likely be more efficient than creating a new object each time you call the function.
Note: since JS refers to object by reference, you will have to make sure that your code is not elsewhere hanging on to that object and expecting it to keep its value.
Prior answer:
In all programming (regardless of how good the optimizer is), you are always better caching a result calculated as a result of accessing several member variables that you are using over and over again in the same function rather than recalling the function that calculates it over and over.
So, if you are calling obj.getCurrentGridPos() more than once and conditions have not changed such that it might return a different result, then you should cache it's value locally (in any language). This is just good programming.
var currentPos = obj.getCurrentGridPos();
And, then use that locally cached value:
if (obj.gridPos == currentPos) {
The interpreter may not be able to do this type of optimization for you because it may not be able to tell whether other operations might cause obj.getCurrentGridPos() to return something different from one call to another, but you the programmer can know that.
One other thing. If obj.getCurrentGridPos() returns an actual object, then you probably don't want to be using == or === to compare objects. That compares ONLY to see if they are literally the same object - it does not compare to see if the two objects have the same properties.
This question is VERY difficult to answer because of all the different javascript engine's out there. The "big 4" of browsers all have their own javascript engine/interpreter and each one is going to do their allocation, caching, GCing, etc.. differently.
The Chrome (and Safari) dev tools have a profiling tab where you can profile memory allocation, timings, etc of your code. This will be a place to start (at least for Chrome and Safari)
I'm not certain if IE or Firefox offer such tools, but I wouldn't be surprised if some third party tools exist for these browsers for testing such things...
Also, for reference -
Chrome uses the V8 javascript engine
I.E uses the Triton (I think it's still called that?) javascript engine
Firefox I believe uses Spidermonkey
Safari I'm not sure about, but think it's using the one that's part of WebKit.
It's my understanding that garbage collection stops execution on most JS engines. If you're going to be making many objects per iteration through your game loop and letting them go out of scope that will cause slowdown when the garbage collector takes over.
For this kind of situation you might consider making a singleton to pool your objects with a method to recycle them for reuse by deleting all of their properties, resetting their __proto__ to Object.prototype, and storing them in an array. You can then request recycled objects from the pool as needed, only increasing the pool size when it runs dry.
The short answer is to set one current position object and check against itself as you're literally going to use more memory if you create a new object every time you call getCurrentGridPos().
There may be a better place for the is this a new position check since you should only do that check once per iteration.
It seems optimal to set the currentGridPos using a RequestAnimationFrame and check against its current x y z positions before updating it so you can then trigger a changedPosition type event.
var currentPos = {
x:0,
y:0,
z:0
}
window.requestAnimationFrame(function(newPos){
if (currentPos.x != currentPos.x || currentPos.y != currentPos.y || currentPos.z != newPos.z) {
$.publish("positionChanged"); // tinypubsub https://gist.github.com/661855
}
})
So, just to be clear, yes I think you should keep an outer "work" point object that updates every iteration... and while it's updating you could check to see if its position has changed - this would be a more intentful way to organize the logic and ensure you don't call getCurrentPos more than once per iteration.
Related
I am learning about GC's and I know there's a thing called HandleScope which 'protects' your local variables from the GC and updates them if a gc heap copy happens. For example, if I have a routine which adds togother 2 values and I call it, it may invoke the garbage collector which will copy the Object that my value is pointing to (or the GC will not even know that the Object the value is pointing to is referenced). A really minimal example:
#include <vector>
Value addValues(Value a, Value b);
std::vector<Value*> gc_vals_with_protection;
Value func(Value a, Value b)
{
vars.push_back(&a); // set protection for a
gc_vals_with_protection.push_back(&b); // set protection for b
Value res = addValues(a, b); // do calcuations
gc_vals_with_protection.pop_back(); // remove protection for b
gc_vals_with_protection.pop_back(); // remove protection for a
return res;
}
But this has got me thinking, it will mean that a and b will NEVER be on the physical CPU registers because you have taken their addresses (and CPU registers don't have addresses) which will make calcuations on them inefficient. Also, at the beggining of every function, you would have to push back twice to the vector (https://godbolt.org/z/dc6vY1Yc5 for assembly).
I think I may be missing something, as this must be not optimal. Is there any other trick I am missing?
(V8 developer here.)
Do languages like JS with a copying GC ever store anything on the cpu registers?
Yes, of course. Pretty much anything at all that a CPU does involves its registers.
That said, JavaScript objects are generally allocated on the heap anyway, for at least the following reasons:
(1) They are bigger than a register. So registers typically hold pointers to objects on the heap. It's these pointers, not the objects themselves, that Handles are needed for (both to update them, and to inform the GC that there are references to the object in question, so the object must not be freed).
(2) They tend to be much longer-lived than the typical amount of time you can hold something in a register, which is only a couple of machine instructions: since the set of registers is so small, they are reused for something else all the time (regardless of JavaScript or GC etc), so whatever they held before will either be spilled (usually though not necessarily to the stack), or re-read from wherever it originally came from next time it's needed.
(3) They have "pointer identity": JavaScript code like obj1 === obj2 (for objects, not primitives) only works correctly when there is exactly one location where an object is stored. Trying to store objects in registers would imply copying them around, which would break this.
There is certainly some cost to creating Handles; it's faster than adding something to a std::vector though.
Also, when passing Handles from one function to another, the called function doesn't have to re-register anything: Handles can be passed around without having to create new entries in the HandleScope's backing store.
A very important observation is that JavaScript functions don't need Handles for their locals. When executing JavaScript, V8 carefully keeps track of the contents of the stack (i.e. spilled contents of registers), and can walk and update the stack directly. HandleScopes are only needed for C++ code dealing with JS objects, because this technique isn't possible for C++ stack frames (which are controlled by the C++ compiler). Such C++ code is typically not the most critical performance bottleneck of an app; so while its performance certainly matters, some amount of overhead is acceptable.
(Side note: one can "blindly" (i.e. without knowledge about their contents) scan C++ stack frames and do so-called "conservative" (instead of "precise") garbage collection; this comes with its own pros and cons, in particular it makes a moving GC impossible, so is not directly relevant to your question.)
Taking this one step further: sufficiently "hot" functions will get compiled to optimized machine code; this code is the result of careful analysis and hence can be quite aggressive about keeping values (primarily numbers) in registers as long as possible, for example for chains of calculations before the final result is eventually stored in some property of some object.
For completeness, I'll also mention that sometimes, entire objects can be held in registers: this is when the optimizing compiler successfully performs "escape analysis" and can prove that the object never "escapes" to the outside world. A simple example would be:
function silly(a, b) {
let vector = {x: a, y: b};
return vector.x + vector.y;
}
When this function gets optimized, the compiler can prove that vector never escapes, so it can skip the allocation and keep a and b in registers (or at least as "standalone values", they might still get spilled to the stack if the function is bigger and needs those registers for something else).
So my simple question is :
Which is the best solution ( performance and memory wise) in this case :
A. we process the variable into a new one and use it everywhere we need :
// imagine (a) is an incomming variable that
// we can't change or else we will break something
var a = "carrots";
var b = a.substr(0,a.length-1);
// and then use b everywhere
B. we process the variable on the fly:
// imagine (a) is an incomming variable that
// we can't change or else we will break something
var a = "carrots";
// and then use "a.substr(0,a.length-1);" everywhere
Please, it's not about how code is written ,is all about which one is faster and better.
Which one you choose and why?
Obviously the first approach is faster. Since we are calling a method and access a property, this is like magnitudes slower than just use/access a resulting string value.
Don't get me wrong, in absolute numbers this still seems like micro optimization, but in this universe and relation it's speed of light vs. a train.
By the way, the concept of storing and caching values in ECMAscript is very commonly used and right so (for different reasons like avoiding scope chains and prototype lookups).
Agreeing with jAndy. I just wanted to add an example and hopefully give another take.
The first approach is far faster.
Each time we call substring we will need to run through the string and create a new substring object on which to operate on in the future. We must run a method and create a new substring which is clearly more costly.
Think about it this way. You could do something (which costs the same amount as the other option lets say x ) one time, or do this x thing a theoretically unlimited time. You are looking at a cost of x vs infinity.
In theory you are potentially taking up less memory in the second. The var b will hold some memory (depends on the language) in java a string takes up 8 bytes. That will persist until the program closes. Instead if you substring each time you will create a value and then clean it once it is no longer used.
Does that make sense?
We create our var b and keep it around until the program closes (is no longer needed). Or we can create a variable a.substring but remove it when it is no longer needed. Technically depending on how the program works you may have less memory if you had say 100's of these over the entire process. However the memory used is negligible and garbage collection does not occur often enough (in normal conditions) for this to actually be true / relevant.
Memory saving is negligible and time complexity is comparatively significant.
Example A is far superior. Why would you in real life ever do the same thing many times if you can accomplish it by doing it just once?
I agree with jAndy.
The first example is going to be faster. You are caching the variable into b so the function you are calling on a is only called once. In your second example everytime you want to use a.substr() you will need to call the function.
So in the first example, you will call a.substr(0, a.length-1) once and cache the result to be used. In example two it will take n times as long where n is the number of times you are calling a.substr(0, a.length-1).
Depending on the what you are doing, there may be no noticeable difference at all. However, the first way is technically faster.
Also, as the comments on jAndy's answer suggest, it is better code since you do not need to repeated call a.substr(0, a.length-1), since you can just cache that.
Javascript arrays used to be just objects with some special syntax, but JIT engines can optimize the array to behave like a true array with O(1) access rather than O(log n) access. I am currently writing a cpu intensive loop where I need to a certain I get O(1) access rather than O(log n). But the problem is that I may need to do array [5231] = obj1 right after its created but the array will eventually be filled. I am worried that such behaviour may trick the JIT to thinking that I am using it as a sparse array and thus I wouldnt get O(1) access time I require. My question is that is there ways I can tell or at least hint the javascript engine that I want a true array?
In particular, do I need to initialize the array with values first? Like fill all of it with reference to a dummy object (my array will only contain references to objects of same prototype or undefined). Would just set the array.length = 6000 be enough?
EDIT: based on http://jsperf.com/sparse-array-v-true-array, it seems filling the array beforehand is a good idea.
I realized I have made a big derp on my profiling test because it is an animation program with varying frame rate and my profiling was focused on detecting where the cpu intensive parts are. It was not suitable in comparing between the two methods as one method would simply run slower but the relative cpu time between different function calls would be the same.
Anyhow, I wrote a test on jspref: http://jsperf.com/sparse-array-v-true-array and (unless I made an error , which so, please do correct me!) A randomly accessed array without filling it first runs twice slower in Chrome and Firefox compared to filled version. So it seems that it is a good idea to fill it in first if you are writing things like a spatial hashmap.
I'm maintaining a JavaScript code where a function that does some heavy processing to generate arrays saves the results in a cache variable inside the function itself. It's implemented like this:
function heavyProcessingStuff(x) {
if(heavyProcessingStuff.cache == undefined)
heavyProcessingStuff.cache = [];
if(heavyProcessingStuff.cache[x] != undefined) {
return heavyProcessingStuff.cache[x]
} else {
return heavyProcessingStuff.cache[x] = x + 1
}
}
The weird thing is that there's a function executed when the page is unloaded that manually deletes every property of the cache variable, like this:
for (n in heavyProcessingStuff.cache) {
delete heavyProcessingStuff.cache[n]
}
I'm confused about why this was implemented this way.
Is this specific for some weird corner case? Is there any motivation to do so? Doesn't/shouldn't the browser garbage collect everything when the page closes?
Javascript uses garbage collection and it is best not to free memory explicitly. Good reading on this is in "De-referencing Misconceptions" in the article "Writing Fast, Memory-Efficient JavaScript".
A quote from the article:
It’s not possible to force garbage collection in JavaScript. You
wouldn’t want to do this, because the garbage collection process is
controlled by the runtime, and it generally knows best when things
should be cleaned up.
Without seeing the full context, there is one other possibility:
Earlier versions of IE (I know IE6 was susceptible), used a simple reference counting system for garbage collection. The trouble is that the DOM and JavaScript kept separate reference stacks.
This allowed for a situation to develop where the DOM (via an expando property) could hold onto a JavaScript reference -- and the JavaScript held onto a DOM reference.
This circular references would create a memory leak that lived on beyond the page, and the memory was only released when the page window was closed.
It was common to use the unload event to free memory and release any event handlers in an effort to avoid this.
In Chrome and Internet Explorer (or any browser that implements a process-per-tab model), you're right, there's absolutely no value. In fact, it's wasting CPU time to try and delete, since often when a tab is closed a process is killed, freeing up all non-shared resources.
For browsers that are a single process (Firefox still is, though progress is underway to change that), it's possible this could make the garbage collector do its work faster, if the reference counts get decremented to 0, but it's probably also pointless. Other than very old (IE6 for example) browsers, every modern garbage collector will probably sweep away everything on the next pass regardless of whether you explicitly remove references or not.
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.