ale*_*lex 23 javascript c memory arrays typed-arrays
我一直在使用JavaScript中的Typed Arrays.
var buffer = new ArrayBuffer(16);
var int32View = new Int32Array(buffer);
Run Code Online (Sandbox Code Playgroud)
我想象普通数组([1, 257, true])在JavaScript中性能较差,因为它们的值可以是任何类型,因此,在内存中达到偏移量并非易事.
我原本以为JavaScript数组下标的工作方式与对象相同(因为它们有许多相似之处),并且基于哈希映射,需要基于散列的查找.但我没有找到太多可信的信息来证实这一点.
所以,我假设Typed Arrays表现如此出色的原因是因为它们像C中的普通数组一样工作,它们总是被输入.给出上面的初始代码示例,并希望获得类型化数组中的第10个值...
var value = int32View[10];
Run Code Online (Sandbox Code Playgroud)
Int32,因此每个值必须由32位或4字节组成.10.<array offset> + (4 * 10),然后读取4字节以获得总值.我基本上只想确认我的假设.我的想法是否正确,如果没有,请详细说明.
我检查了V8源代码,看看我是否可以自己回答,但我的C生锈了,我对C++不太熟悉.
Ash*_*ain 44
由于性能原因,TypeGL Arrays由WebGL标准委员会设计.通常Javascript数组是通用的,可以保存对象,其他数组等等 - 并且元素在内存中不一定是顺序的,就像它们在C中一样.WebGL要求缓冲区在内存中是顺序的,因为这就是底层C API所期望的他们.如果不使用Typed Arrays,将普通数组传递给WebGL函数需要大量工作:必须检查每个元素,检查类型,如果它是正确的(例如浮点数),则将其复制到单独的顺序类C缓冲区,然后将该顺序缓冲区传递给C API.哎哟 - 很多工作!对于性能敏感的WebGL应用程序,这可能会导致帧速率大幅下降.
另一方面,正如您在问题中所建议的那样,Typed Arrays在其幕后存储中已经使用了顺序C类缓冲区.当您写入类型化数组时,您确实在后台分配了一个类似C的数组.出于WebGL的目的,这意味着缓冲区可以由相应的C API直接使用.
请注意,您的内存地址计算还不够:浏览器还必须检查数组,以防止超出范围的访问.这必须发生在任何类型的Javascript数组中,但在许多情况下,聪明的Javascript引擎可以省略检查,因为它可以证明索引值已经在边界内(例如从0循环到数组的长度).它还必须检查数组索引是否真的是一个数字而不是字符串或其他东西!但它本质上就像你描述的那样,使用类似C的寻址.
但是......那还不是全部!在某些情况下,聪明的Javascript引擎也可以推断出普通Javascript数组的类型.在像V8这样的引擎中,如果你创建一个普通的Javascript数组并且只存储浮点数,V8可以乐观地决定它是一个浮点数组并优化它为它生成的代码.然后,性能可以等同于类型化数组.因此,实际上不需要类型化数组来达到最大性能:只是可预测地使用数组(每个元素都是相同类型),并且一些引擎也可以优化它.
那么为什么类型化数组仍然需要存在?
因此,简而言之,普通数组在理论上可以与类型数组一样快.但是,类型化阵列可以更轻松地达到最佳性能.
是的,你大多是正确的.使用标准的JavaScript数组,JavaScript引擎必须假设数组中的数据是所有对象.它仍然可以将其存储为类似C的数组/向量,其中对内存的访问仍然与您描述的一样.问题是数据不是值,而是引用该值(对象)的东西.
因此,执行a[i] = b[i] + 2需要引擎:
使用类型化数组,引擎可以:
注意:这些不是JavaScript引擎将执行的确切步骤,因为这取决于正在编译的代码(包括周围代码)和相关引擎.
这允许得到的计算更有效.此外,类型化数组具有内存布局保证(n字节值的数组),因此可用于直接与数据(音频,视频等)接口.