JavaScript中类型化数组的优点是它们在C中的工作方式相同还是相似?

JavaScript中类型化数组的优点是它们在C中的工作方式相同还是相似?,javascript,c,arrays,memory,typed-arrays,Javascript,C,Arrays,Memory,Typed Arrays,我一直在玩JavaScript var buffer = new ArrayBuffer(16); var int32View = new Int32Array(buffer); 我认为JavaScript中的普通数组([1257,true])的性能很差,因为它们的值可以是任何类型的,因此,在内存中达到一个偏移量并不容易 我最初认为JavaScript数组下标的工作原理与对象相同(因为它们有许多相似之处),并且是基于对象的,需要基于哈希的查找。但我还没有找到多少可信的信息来证实这一点 因此,我

我一直在玩JavaScript

var buffer = new ArrayBuffer(16);
var int32View = new Int32Array(buffer);
我认为JavaScript中的普通数组(
[1257,true])
的性能很差,因为它们的值可以是任何类型的,因此,在内存中达到一个偏移量并不容易

我最初认为JavaScript数组下标的工作原理与对象相同(因为它们有许多相似之处),并且是基于对象的,需要基于哈希的查找。但我还没有找到多少可信的信息来证实这一点

因此,我假设类型化数组之所以表现如此出色,是因为它们与C中的普通数组一样工作,它们总是类型化的。给出上面的初始代码示例,并希望获得类型化数组中的第10个值

var value = int32View[10];
  • 类型为
    Int32
    ,因此每个值必须由
    32
    位或
    4
    字节组成
  • 下标为
    10

  • <> LI>内存中的值是<代码>,看看我自己是否能回答,但是我的C是生锈的,我对C++不太熟悉。

    < P>我不是真正的贡献者,任何JavaScript引擎,只有V8上的一些读数,所以我的答案可能不是完全正确的:

    数组中的井值(只有没有孔/间隙的普通数组,而不是稀疏数组。稀疏数组被视为对象)都是指针或具有固定长度的数字(在v8中,它们是32位的,如果是31位整数,则最后用
    0
    位标记,否则它就是指针)

    所以我不认为查找内存位置与typedArray有什么不同,因为整个数组中的字节数都是相同的。但是不同的是,如果它是一个对象,那么你必须添加一个取消装箱层,这在普通的TypeDarray中是不会发生的

    当然,在访问typedArrays时,肯定并没有普通数组所具有的类型检查功能(尽管这可能会在高度优化的代码中被删除,而这只是为热代码生成的)

    对于写作来说,如果是同一种类型,速度应该不会慢很多。如果它是不同的类型,那么JS引擎可能会为它生成多态代码,这会更慢


    您也可以尝试在jsperf.com上制作一些基准测试来确认。

    是的,您基本上是正确的。对于标准JavaScript数组,JavaScript引擎必须假设数组中的数据都是对象。它仍然可以将其存储为类似C的数组/向量,其中对内存的访问仍然与您描述的一样。问题在于数据不是值,而是引用该值(对象)的东西

    因此,执行
    a[i]=b[i]+2
    需要发动机:

  • 在索引i处访问b中的对象
  • 检查对象的类型
  • 从对象中提取值
  • 在值上加2
  • 使用4中新计算的值创建一个新对象
  • 将步骤5中的新对象分配到at索引i中
  • 使用类型化数组,引擎可以:

  • 访问索引i处b中的值(包括将其放入CPU寄存器)
  • 将该值增加2
  • 将步骤2中的新对象分配到at索引i中
  • 注意:这些不是JavaScript引擎将执行的确切步骤,因为这取决于正在编译的代码(包括周围的代码)和正在讨论的引擎


    这使得计算结果更加有效。此外,类型化阵列具有内存布局保证(n字节值的阵列),因此可用于直接与数据(音频、视频等)接口。

    出于性能原因,类型化阵列由WebGL标准委员会设计。通常,Javascript数组是通用的,可以保存对象、其他数组等,并且元素在内存中不一定是顺序的,就像在C中一样。WebGL要求缓冲区在内存中是顺序的,因为底层的C API就是这样期望它们的。如果不使用类型化数组,则将普通数组传递给WebGL函数需要大量工作:必须检查每个元素,检查类型,如果它是正确的(例如浮点),则将其复制到单独的顺序C类缓冲区,然后将该顺序缓冲区传递给C API。哎哟,干了好多活!对于性能敏感的WebGL应用程序,这可能会导致帧速率大幅下降

    另一方面,正如您在问题中所建议的,类型化数组在其后台存储中已经使用了一个类似于C的顺序缓冲区。当您写入类型化数组时,实际上是在幕后为类C数组赋值。就WebGL而言,这意味着相应的C API可以直接使用缓冲区

    请注意,您的内存地址计算还不够:浏览器还必须检查数组,以防止超出范围的访问。这必须发生在任何类型的Javascript数组中,但在许多情况下,聪明的Javascript引擎可以在证明索引值已经在范围内(例如从0循环到数组长度)时忽略检查。它还必须检查数组索引是否真的是一个数字,而不是字符串或其他东西!但本质上就像你所描述的,使用类似C的寻址

    但是…还不止这些!在某些情况下,聪明的Javascript引擎还可以推断出普通Javascript数组的类型。在像V8这样的引擎中,如果创建一个普通的Javascript数组,并且只在其中存储浮点数,V8可能会乐观地确定它是一个浮点数数组,并优化它为此生成的代码。这样,性能就相当于类型化数组。因此,类型化数组实际上并不是达到最高性能所必需的:只需可预测地使用数组(每个元素的类型都相同),一些引擎也可以为此进行优化

    那么,为什么类型化数组仍然需要存在呢

    • 优化方法,如推断