alt.126
alt.126

Reputation: 1107

What are the speed diferences between object's property access and normal variable access?

Before fully defining my question, I must say that >>this question/answer<< doesn't answer my problem, and I have proven it to myself that the given answer doesn't match at all with the actual effect of property vs. variable or cached property (see below).

I have been using HTML5 canvas, and I write raw pixel blocks many times in a second in a 640x480 area.

As advised by some tutorials, it is good to cache the .data property of an ImageData variable (in this case, it would be _SCimgData).

If I cache that property in SC_IMG_DATA, I can putImageData repeatedly in the Canvas with no problem; but if I repeatedly access it directly with _ScimgData.data, the slow-down of the code is noticieable (taking nearly 1 second to fill a single 640x480 Canvas):

var SomeCanvas  = document.getElementById("SomeCanvas");
var SCContext   = SomeCanvas.getContext("2d");
var _SCimgData  = SomeCanvas.getImageData(0, 0, 640, 400);
var SC_IMG_DATA = _SCimgData.data;



Now I have the following doubt:

Would my code be as slow for other kinds of similar accesses?

I need an array of objects for a set of functions that can have several "instances" of an object (created by a regular utility function), and that need the index of the instance in an array of objects, either to create/initialize it, or to update its properties.

My concrete example is this:

var objArray=new Array();
var objArray[0]=new Object();
    objArray[0].property1="some string property";

for(var x=0; x<65536; x++)
 doSomething(objArray[0].property1, objIDX=0);

Would that code become as unacceptably slow as in the Canvas case, if the properties and functions contained in some properties are called very intensively (several times in a single milisecond, of course using setInterval and several "timer threads" to avoid locking the browser)?

If so, what other alternative is there to speed up access for the different properties of several objects in the main object array?





EDIT 1 (2012-08-27)

Thanks for the suggestions. I have up-voted them since I suspect they will be useful for the project I'm working on.

I am thinking in a combination of methods, using mainly Arrays instead of Objects to build an actual array of "base objects", and addressing array elements by numbers (arr[0]) instead of string array keys (arr["zero"]).

var OBJECTS_SIZE=10
var Obj_Instances=new Array();
    Obj_Instances[0]="property or array 1 of Object 0";
    Obj_Instances[1]=new Array();
    Obj_Instances[1][0]=new ArrayBuffer(128);
    Obj_Instances[1][1]=new DataView(Obj_Instances[1][0]);
    Obj_Instances[2]="property or array 3 of Object 0";
    Obj_Instances[3]=function(){alert("some function here")};
    Obj_Instances[4]="property or array 5 of Object 0";
    Obj_Instances[5]="property or array 6 of Object 0";
    Obj_Instances[6]=3;
    Obj_Instances[7]="property or array 8 of Object 0";
    Obj_Instances[8]="property or array 9 of Object 0";
    Obj_Instances[9]="property or array 10 of Object 0";

    Obj_Instances[10]="property or array 1 of Object 1";
    Obj_Instances[11]=new Array();
    Obj_Instances[11][0]=new ArrayBuffer(128);
    Obj_Instances[11][1]=new DataView(Obj_Instances[11][0]);
    Obj_Instances[12]="property or array 3 of Object 1";
    Obj_Instances[13]=function(){alert("some function there")};
    Obj_Instances[14]="property or array 5 of Object 1";
    Obj_Instances[15]="property or array 6 of Object 1";
    Obj_Instances[16]=3;
    Obj_Instances[17]="property or array 8 of Object 1";
    Obj_Instances[18]="property or array 9 of Object 1";
    Obj_Instances[19]="property or array 10 of Object 1";

function do_Something_To_Property_Number_6(objIdx)
{
 //Fix the index to locate the base address
 //of the object instance:
 ///
   objIdx=(objIdx*OBJECTS_SIZE);
   Obj_instances[objIdx+6]++;   //Point to "Property" 6 of that object
}

I would have, say an "instance" of an "object" that takes up the first 10 array elements; the next "instance" would take the next 10 array elements, and so on (creating the initialization in a custom "constructor" function to add the new block of array elements).

I will also try to use jsPerf and JSHint to see which combination result better.

Upvotes: 4

Views: 2493

Answers (3)

Pebbl
Pebbl

Reputation: 35995

I realise this is not quite answering your question (as it has already been answered), however as you seem to be looking for speed improvements in regard to function calls that happen thousands of times (as others who find this might also be doing). I thought I'd include this here as it goes against assumptions:

An example function:

var go = function (a,b,c,d,e,f,g,h) {
  return a+b+c+d+e+f+g+h;
}

The following is how you would normally call a repetitive function:

var i=500000; while(i--){
  go(1,2,3,4,5,6,7,8);
}

However, if none (or a few) of those arguments ever change for this particular usage of the function, then it's far better to do this (from a speed pov - obviously not an asynchronous pov):

var i=500000; go.args = [1,2,3,4,5,6,7,8];
while(i--){
  go();
}

In order for the above to work you only need a slight modification to the original function:

var go = function (a,b,c,d,e,f,g,h, i) {
  if ( go.args ) {
    i = go.args;
    a = i[0]; b = i[1];
    c = i[2]; d = i[3];
    e = i[4]; f = i[5];
    g = i[6]; h = i[7];
  }
  return a+b+c+d+e+f+g+h;
}

This second function runs significantly faster because you are not passing in any arguments (a function called with no args is very quick to initiate). Pulling the values from the .args array doesn't seem to be that costly either (unless you involve strings). Even if you update one or two of the args it's still far faster, which makes it perfect for pixel or imagedata manipulations because you are normally only shifting x & y:

var i=500000; go.args = [1,2,3,4,5,6,7,8];
while(i--){
  go.args[2] = i;
  go();
}

So in a way this is an example of where an object property can be faster than local vars - if a little convoluted and off topic ;)

Upvotes: 4

Peter Olson
Peter Olson

Reputation: 142921

Possible browser optimizations notwithstanding, accessing a property of an object is more expensive than accessing a local variable (but not necessarily a global variable or a variable of a parent function).

The deeper the property, the more of a performance hit you take. In other words,

for(var x=0; x<65536; x++) 
 doSomething(objArray[0].property1, objIDX=0); 

would be improved by caching objArray[0].property1, and not repeatedly assigning to objIDX:

var prop = objArray[0].property1;
objIDX = 0;
for(var x=0; x<65536; x++) 
 doSomething(prop, 0); 

Upvotes: 3

Joseph
Joseph

Reputation: 119837

To answer your "doubts", I suggest using JSPerf to benchmark your code. One can't really tell by code alone if the procedure is faster than another unless tested.

Also, I suggest you use the literal notation for arrays and objects instead of the new notation during construction:

var objArray=[
    {
        property : 'some string property'
    }, {
        ...
    },
];

Also, based on your code, it's better to have this since you are using the same object per iteration:

var obj = objArray[0].property1,
    objIDX = 0;

for(var x=0; x<65536; x++){
    doSomething(obj,objIDX);
}

Upvotes: 3

Related Questions