Any performance difference between data from function arguments vs assigned variable? - javascript

This might sound like a noob question but here goes;
Basically, I'm passing a large amount of data from one object to another. Below is a simplified example.
// Example 1
function Person(hugeData) {
this.info = function() {
console.log(hugeData);
}
}
Homer = new Person(hugeData);
Homer.info();
Compared with
// Example 2
function Person() {
var hugeData;
this.set = function(data) {
hugeData = data;
}
this.info = function() {
console.log(hugeData);
}
}
Homer = new Person();
Homer.set(hugeData);
Homer.info();
Is there much of a difference performance-wise between the two code snippets? Please focus on the context of the example rather than the code itself (setting object variable vs passing by arguments).
While the example above is for Javascript, I would also like to know if the same principle applies for other programming languages like PHP.
Thanks.

No, not at all.
Without going into much detail now, both, formal paramters and local variables are stored within the such called Activation Object (in ES3) or the Lexical Environment Record (ES5) under the hood.
So access times should be identical by spec.
If you want to know the details, checkout:
http://dmitrysoshnikov.com/ecmascript/javascript-the-core/
and
http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-2-lexical-environments-ecmascript-implementation/
Testcase: http://jsperf.com/formal-parameters-vs-local-variables-access-time

I assume the major point of your question is whether this line...
hugeData = data;
... in your code may affect the performance.
And the answer is no, it's not (at least not so it can affect the application's performance).
If hugeData refers to an object (and remember arrays in JS are essentially objects), it actually stores only a reference to this object. And the reference is what will be copied, without any duplication of the object's contents.
If hugeData refers to a string, it can be a bit more complicated... but as far as I know, most modern browsers (check MDN, as example) now implement 'copy-on-writing' technique. In other words, the string won't be duplicated here as well.

Passing by variable is the best thing. Because it's obvious your huge data is not a primitive so you are going to only refer that in the functions context.
Look at jAndy's answer.

It's hard to generalize in this case because every implementation of Javascript is different.
I could imagine that when you pass a big hunk of data with the creation of an object, you are saving a reallocation of memory, which would happen when you create the object with few data first and then add a lot of data to it later. But most JS implementation will store the big data chunk in a reference anyway, so it is unlikely that it really matters.

Related

Global Javascript Properties - memory usage

I'm building various d3.js dashboards which frequently refer to a javascript_properties.js file which includes properties such as:
var all_charts = (function() {
return {
width:860,
height:500,
from_date:"",
to_date:"",
highlight_color:"#00FFFF"
}
}());
I use these properties frequently within various functions.
My question is:
Is there any harm in calling each property direct every time I use it or would it be more efficient to declare a local variable at the beginning of each function if a property is going to be called more than once?
To show an example. A local variable:
var width = all_charts.width;
OR calling
all_charts.width
as many times as required during a function.
There may be little discernible difference?
This isn't about memory usage, it's about lookup time.
Yes, caching the property to a local variable may make it faster when using that repeatedly afterward, as the JavaScript engine doesn't have to traverse the scope chain up to the global level to find all_charts and then look up width on it.
But, it's unlikely to make a noticeable difference unless you're using these properties hundreds of thousands of times in the same function.
Side note: There's no point to the function in the all_charts code, what you have does exactly what this does, just more indirectly:
var all_charts = {
width:860,
height:500,
from_date:"",
to_date:"",
highlight_color:"#00FFFF"
};

Is it necessary to nullify primitive values for grabage collection?

If I have the following code:
function MyClass() {
this.data = {
// lots of data
};
}
var myClassInstace = new MyClass();
var myobj = {
num:123,
str:"hello",
theClass:myClassInstance
};
I know it's absolutely necessary to do:
myobj.theClass = null;
To free up myClassInstance and its data property for GC. However, what should I do with myobj.num and myobj.str? Do I have to give them a value of null too? Does the fact that they're primitive change anything regarding GC?
The JavaScript runtime that implements garbage collection will be able to collect items as soon as values are no longer reachable from code. This is true for object references as well as primitives. The details of the exact moment the item is collected varies by implementation, but it is not even necessary to set your object references to null (as you state) unless you need the object cleaned up sooner than the natural termination of the current function.
This all ties into the fundamental concept of "scope" and the Scope Chain. When an item is no longer in any other objects scope chain it can be collected. Understanding this clearly will answer this question and also help to understand closures, which are scenarios where items stay in memory longer than you might have expected.
There are a lot of "it depends here", ranging from what your code is doing to what browser you're running in. However, if your object is JIT compiled to not use a map for its attributes, then the number should be an 8 byte double stored inline inside the object. Nulling it will do nothing.
The string and the myclass instance will be a pointer to memory allocated outside the object (since a string can be arbitarily many bytes, it can't be stored inside the object. A compiler could conceivably store one instance of the string in memory and never free it, however). Nulling them can allow the garbage collector to free them before the main object goes out of scope.
However, the real question is why you're worried about this. Unless you have profiled your code and identified garbage collection or memory leaks as a problem, you should not be trying to optimize GC behavior. In particular, unless your myobj object is itself going to be live for a long time, you should not worry about nulling fields. The GC will collect it when it goes out of scope.
setting to undefined (not null) will work however delete is better example delete myobj.theClass
Just to avoid misunderstanding I will say that there is no way to really delete an object from memory in JavaScript. you delete it's references or set them to undefined so that the GC can do it's work and really delete.

When should I prefer a clone over an reference in javascript?

at the moment I'm writing a small app and came to the point, where I thought it would be clever to clone an object, instead of using a reference.
The reason I'm doing this is, because I'm collecting objects in a list. Later I will only work with this list, because it's part of a model. The reference isn't something I need and I want to avoid having references to outside objects in the list, because I don't want someone to build a construct, where the model can be changed from an inconsiderate place in their code. (The integrity of the information in the model is very important.)
Additional I thought I will get a better performance out of it, when I don't use references.
So my overall question still is: When should I prefer a clone over an reference in javascript?
Thanks!
If stability is important, then clone it. If testing shows that this is a bottleneck, consider changing it to a reference. I'd be very surprised if it is a bottleneck though, unless you have a very complicated object which is passed back and forth very frequently (and if you're doing that it's probably an indication of a bad design).
Also remember that you can only do so much to save other developers from their own stupidity. If they really want to break your API, they could just replace your functions with their own by copying the source or modifying it at runtime. If you document that the object must not be changed, a good developer (yes, there are some) will follow that rule.
For what it's worth, I've used both approaches in my own projects. For small structs which don't get passed around much, I've made copies for stability, and for larger data (e.g. 3D vertex data which may be passed around every frame), I don't copy.
Why not just make the objects stored in the list immutable? Instead of storing simple JSON-like objects you would store closures.
Say you have an object with two properties A and B. It looks like that:
myObj = {
"A" : "someValue",
"B" : "someOtherValue"
}
But then, as you said, anyone could alter the state of this object by simply overriding it's properties A or B. Instead of passing such objects in a list to the client, you could pass read-only data created from your actual objects.
First define a function that takes an ordinary object and returns a set of accessors to it:
var readOnlyObj = function(builder) {
return {
getA : function() { return builder.A; },
getB : function() { return builder.B; }
}
}
Then instead of your object myObj give the user readOnlyObj(myObj) so that they can access the properties by methods getA and getB.
This way you avoid the costs of cloning and provide a clear set of valid actions that a user can perform on your objects.

Can I replace s standard DOM functions like removeChild?

Can I replace s standard DOM functions like removeChild to show for example alert before some node removed from parent? Something like that but my example is with errors
var original = node.removeChild;
node.removeChild = function(node, original){
alert('message');
original(node);
}
If you want to apply this across the document do this
var original = Node.prototype.removeChild;
Node.prototype.removeChild = function(node) {
//custom logic
original.apply(this, arguments);
}
If you want to apply the change only to a selected node then
var original = node.removeChild;
node.removeChild = function(node){
//custom logic
original.apply(this, arguments);
}
First of all, the usage of the new keyword is completely incorrect. That will severely change the behaviour. function is an instance of Function, the "mothership" of all JavaScript functions.
When using the new keyword, the function will be immediately executed and the behaviour very different from what you expect. See Section 13 of the ECMA Language Specification for more details on how to create function objects. Read it here, at page 98.
Second, it is strongly discouraged to alter any native object prototype. It leads to the most tedious and painful bugs in human history. Anybody coming in after you to edit the code will spend a long time before figuring out where that alert originates from.
Keep those two actions separate, they are completely unrelated. Wrapping them up in a prototype function is very bad design, for the above reason any many more, such as:
Using for in loops. You will iterate through more properties that you should if you forget to use hasOwnProperty.
Yourself and other developers will have a hard time figuring out why random things are happing with a basic DOM Node remove operation occurs.(you will forget, happens to everybody).
I am going to be radical an just say no. While it may technically work on the browsers you care about and be the basis for prototype.js, you should never modify DOM objects, or their prototypes, like this.
There is a long post on the topic: http://perfectionkills.com/whats-wrong-with-extending-the-dom/ but the TL;DR is that these are "hosted objects" and modification to their behavior is not guaranteed. It may work today on browser x but there's no guarantee about browser y or even x tomorrow.
Your implementation looks fine, except that you don't need to pass original as an argument there.
var original = node.removeChild;
node.removeChild = function(node) {
alert('message');
original(node);
}

Best practice: Javascript/Jquery saving variable for later use

I'm sure, this question has been answered somewhere before but I just couldn't find it.
If within a function a variable has been defined, what is the best practice to save it for later use? 1. Saving it "globally"?
foo = 'bar';...function bar(){
...
foo = 'bat';
return foo;
}...
Here, the variable will be altered later on.
2. Or saving it within a hidden form field within the HTML-DOM?
`Thanxs!
Saving it as a global JavaScript variable is by far the most efficient.
EDIT: If the data you want to save is associated with an element on the page (for example, each row in a table has a bit of data associated with it), and you are using jQuery, there is a data() method which is more efficient than setting an attribute on the element or something similar.
It depends on the context, but probably: In a variable defined at the top level of a closure that wraps the set of functions to which it applies.
i.e.
var exports = function () {
var stored_data;
function set_data(foo) {
stored_data = foo;
}
function get_data() {
return stored_data;
}
return { get: get_data, set: set_data };
}();
This avoids the risk of other scripts (or other parts of your own, potentially very large, script) overwriting it by accident.
The HTML5 spec has defined a solution to this question: If you are using HTML5, you can specify data attributes in your DOM.
See this page for more info: http://ejohn.org/blog/html-5-data-attributes/
This is now the standardised way of doing it, so I guess that it's considered best practice. Also John Resig, who wrote the blog I linked to above, is the author of JQuery, so if it's good enough for him, who am I to argue.
The really good news is that you don't even have to be using an HTML5-compatible browser for this technique to work - it already works in older browsers; it's just that now it's been encoded into the standard, and there's a defined way to do it.
That said, there's nothing wrong with a global variable in your Javascript as long as you avoid polluting the namespace too much, and it would be more efficient from a performance perspective, so there's plenty of merit in that approach as well.

Categories