Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript类型Darray性能_Javascript_Performance_Typed Arrays - Fatal编程技术网

Javascript类型Darray性能

Javascript类型Darray性能,javascript,performance,typed-arrays,Javascript,Performance,Typed Arrays,为什么TypeDarray不比普通阵列快?我想为CLZ(计算前导零函数)使用预计算值。我不想让他们解释成平常的东西 编制代码: Benchmark.prototype.setup = function() { var buffer = new ArrayBuffer(0x10000); var Uint32 = new Uint32Array(buffer); var arr = []; for(var i = 0; i < 0x10000; ++i) {

为什么TypeDarray不比普通阵列快?我想为CLZ(计算前导零函数)使用预计算值。我不想让他们解释成平常的东西

编制代码:

 Benchmark.prototype.setup = function() {
   var buffer = new ArrayBuffer(0x10000);
   var Uint32 = new Uint32Array(buffer);
   var arr = [];
   for(var i = 0; i < 0x10000; ++i) {
     Uint32[i] = (Math.random() * 0x100000000) | 0;
     arr[i] = Uint32[i];
   }
   var sum = 0;
 };
测试2:

sum = Uint32[(Math.random() * 0x10000) | 0];


PS:可能是我的性能测试无效,请随时纠正我。

现代引擎会在幕后使用真正的数组,即使他们认为可以使用
Array
,如果你做了一些让他们认为不能使用真正的数组的事,他们会求助于属性映射“数组”

另请注意,
var buffer=new ArrayBuffer(0x10000)
然后
var Uint32=new Uint32数组(buffer)
生成一个Uint32数组,其大小为0x4000(0x10000/4),而不是0x10000,因为您给出的值
ArrayBuffer
是以字节为单位的,但每个Uint32数组条目当然有四个字节。以下所有内容都使用
新的uint32阵列(0x10000)
来比较苹果和苹果(即使在本次编辑之前也一直如此)

让我们从这里开始,使用新的Uint32Array(0x10000):(遗憾的是,JSPerf已经丢失了这个测试及其结果,现在完全离线)

这表明,由于您以一种简单、可预测的方式填充阵列,现代引擎将继续使用真正的阵列(具有其性能优势),而不是转换。我们看到两者的性能基本相同。速度上的差异可能与类型转换有关,将
Uint32
值作为
数字分配给
sum
(尽管如果类型转换没有延迟,我会感到惊讶…)

不过,这也带来了一些混乱:

var Uint32 = new Uint32Array(0x10000);
var arr = [];
for (var i = 0x10000 - 1; i >= 0; --i) {
  Uint32[Math.random() * 0x10000 | 0] = (Math.random() * 0x100000000) | 0;
  arr[Math.random() * 0x10000 | 0] = (Math.random() * 0x100000000) | 0;
}
var sum = 0;
…因此,引擎不得不依赖老式的属性映射“数组”,您可以看到类型化数组的性能明显优于老式类型:(遗憾的是,JSPerf失去了此测试及其结果)

聪明的,这些JavaScript引擎工程师

不过,您对
数组的非数组性质所做的具体操作很重要;考虑:

var Uint32 = new Uint32Array(0x10000);
var arr = [];
arr.foo = "bar";                            // <== Non-element property
for (var i = 0; i < 0x10000; ++i) {
  Uint32[i] = (Math.random() * 0x100000000) | 0;
  arr[i] = (Math.random() * 0x100000000) | 0;
}
var sum = 0;
…我们回到了类型化数组获胜的问题上——IE11除外:(遗憾的是,JSPerf失去了这个测试及其结果)

这与:

var Uint32 = new Uint32Array(0x10000);
不是因为新的ArrayBuffer(您总是会得到一个数组缓冲区:在这两种情况下请参见Uint32.buffer),而是因为长度参数:使用ArrayBuffer时,每个元素有1个字节,使用Uint32数组时,每个元素有4个字节

因此,在第一种情况下(在您的代码中),Uint32.length=0x1000/4,您的循环4次中有3次超出边界。但遗憾的是,你永远不会犯错误,只有糟糕的表现

使用“new ArrayBuffer”,您必须像这样声明Uint32:

var buffer = new ArrayBuffer(0x10000 * 4);
var Uint32 = new Uint32Array(buffer);

请参阅和。

在您的情况下,性能不佳的原因是,由于阵列长度存在错误,您在使用UINT32阵列时试图读取阵列外部的数据

但如果这不是真正的原因:

尝试使用Int32Array而不是UInt32阵列。我认为在V8中,变量不能有uint32类型,但可以有int32/double/pointer。所以,当您将uint32类型指定给变量时,它将转换为较慢的双精度

如果使用32位版本的V8,则变量可以具有int31/double/pointer类型。因此,int32也将转换为double。但若您使用普通数组,并且所有值都是int31,那个么不需要转换,所以普通数组可以更快

此外,使用int16可能需要进行一些转换才能获得int32(因为符号和1的补码)。 Uint16不需要转换,因为V8只需在左侧添加零


另外,您可能对指针和int31(或x64上的int32)感兴趣,它们在V8中是相同的。这也意味着int32在x64上将需要8个字节。这也是x86上没有int32类型的原因:因为如果我们将所有32位用于存储整数,我们将不再有任何空间来保存指针。

很有趣,谢谢。在实际用例中,情况变得更加复杂,各种对象/数组的连续分配/禁止导致内存碎片,如果内存没有预先分配,处理时间就会爆炸。在现实生活中,由于类型化数组是预先分配的(Rq:js数组也可能是预先分配的…),所以将预先计算的int32值写入类型化数组的速度很快。阵列不包含孔(是的,孔很快,但…)。数组已预分配。因此,创建和初始化类型化数组很快。但是,当您尝试从uint32数组读取时,该值应转换为double(参见下面的答案)。您应该使用Int32Array(在x64上)或Int16Array(在x86上)(再次参见下面的答案)。您删除了jsperf测试吗?我再也找不到了不,我没有把它拿走。这很奇怪。非常非常奇怪,他们会像那样消失!所有这些。。。特别奇怪的是在光照下。我已经搜索过了,以防URL发生了变化或其他什么,但是……什么都没有。我可以找到阵列性能的其他测试,但苏哈诺夫和我的测试除外。我提出了一个建议。当然,如果我们中有更多的人(我只是做了……这是第一次低头),这可能不会有什么坏处。令人遗憾的是,人们接受答案的依据是内容的大小,而不是正确性。@MorrisLiang,我也是这么想的,但后来我意识到,这个答案是在问题提出半年多后发布的。@MorrisLiang:注意,我的答案总是使用
new UINT32阵列(0x10000)
来比较苹果和苹果的长度,并且仍然显示出速度差异。但我并没有像上面提到的那样指出区别。
var buffer = new ArrayBuffer(0x10000);
var Uint32 = new Uint32Array(buffer);
var Uint32 = new Uint32Array(0x10000);
var buffer = new ArrayBuffer(0x10000 * 4);
var Uint32 = new Uint32Array(buffer);