【问题标题】:What are the speed diferences between object's property access and normal variable access?对象的属性访问和普通变量访问之间的速度差异是什么?
【发布时间】:2012-08-26 00:42:51
【问题描述】:

在完全定义我的问题之前,我必须说 >>this question/answer

我一直在使用 HTML5 画布,我在 640x480 区域内在一秒钟内多次写入原始像素块。

根据一些教程的建议,最好缓存ImageData 变量的.data 属性(在这种情况下,它将是_SCimgData)。

如果我将该属性缓存在SC_IMG_DATA 中,我可以在画布中重复putImageData 没有问题;但如果我直接使用_ScimgData.data 重复访问它,代码的减速是显而易见的(需要将近 1 秒来填充单个 640x480 画布):

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



现在我有以下疑问:

对于其他类型的类似访问,我的代码会一样慢吗?

我需要一组函数的对象数组,这些函数可以具有对象的多个“实例”(由常规实用函数创建),并且需要对象数组中实例的索引,或者创建/初始化它,或者更新它的属性。

我的具体例子是这样的:

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);

如果某些属性中包含的属性和函数被非常密集地调用(在一毫秒内多次,当然使用setInterval和几个“计时器线程”以避免锁定浏览器)?

如果是这样,还有什么其他方法可以加快对主对象数组中多个对象的不同属性的访问?





编辑 1 (2012-08-27)

感谢您的建议。我对它们投了赞成票,因为我怀疑它们对我正在从事的项目很有用。

我正在考虑多种方法的组合,主要使用Arrays 而不是Objects 来构建一个实际的“基础对象”数组,并通过数字(arr[0])而不是字符串数组来寻址数组元素键 (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
}

我会说一个“对象”的“实例”,它占据了前 10 个数组元素;下一个“实例”将采用接下来的 10 个数组元素,依此类推(在自定义“构造函数”函数中创建初始化以添加新的数组元素块)。

我也会尝试使用 jsPerf 和 JSHint 看看哪个组合效果更好。

【问题讨论】:

  • 另一个微妙的增强(在已经提到的之上)可以使用x=65536;while(x--){doSomething(...);} 而不是 for... 但前提是您的计数器是否向后移动无关紧要。

标签: javascript arrays performance object properties


【解决方案1】:

要回答您的“疑问”,我建议使用JSPerf 对您的代码进行基准测试。除非经过测试,否则仅凭代码无法真正判断该过程是否

另外,我建议您在构造过程中对数组和对象使用文字表示法,而不是 new 表示法:

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

另外,根据您的代码,最好有这个,因为每次迭代都使用相同的对象:

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

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

【讨论】:

    【解决方案2】:

    我意识到这并不能完全回答你的问题(因为它已经被回答了),但是你似乎正在寻找关于发生数千次的函数调用的速度改进(正如其他发现此问题的人可能也在做的那样)。我想我会把它包括在这里,因为它违背了假设:

    一个示例函数:

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

    以下是您通常调用重复函数的方式:

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

    但是,如果这些参数中没有一个 (或几个) 会因函数的这种特定用途而改变,那么这样做会好得多 (从速度观点来看 - 显然不是一个异步 pov):

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

    为了使上述功能正常工作,您只需对原始功能稍作修改:

    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;
    }
    

    第二个函数的运行速度明显更快,因为您没有传入任何参数(调用不带参数的函数非常快启动)。从 .args 数组中提取值似乎也不那么昂贵(除非您涉及字符串)。即使您更新一两个参数,它仍然快得多,这使其非常适合像素或图像数据操作,因为您通常只移动 x 和 y:

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

    所以在某种程度上,这是一个对象属性可以比本地变量更快的示例 - 如果有点令人费解且离题;)

    【讨论】:

      【解决方案3】:

      尽管有可能的浏览器优化,但访问对象的属性比访问局部变量(但不一定是全局变量或父函数的变量)更昂贵。

      属性越深,您受到的性能影响就越大。换句话说,

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

      将通过缓存objArray[0].property1 来改进,而不是重复分配给objIDX

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

      【讨论】:

      • 难道你不能在理论上将doSomething 函数本地缓存为本地变量吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-27
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      • 2014-04-25
      • 2021-05-21
      相关资源
      最近更新 更多