Javascript类型数组与简单数组:性能

Javascript类型数组与简单数组:性能,javascript,arrays,performance,dynamic-arrays,typed-arrays,Javascript,Arrays,Performance,Dynamic Arrays,Typed Arrays,我基本上想做的是将一组数据点实时映射到WebGL顶点缓冲区(Float32Array)(处理动画参数化曲面)。我假设使用Float32Array(每个组件[xx…x,yy…y]一个Float32Array或交错它们:xyxy…xy)来表示数据点应该比将它们存储在点数组中更快:[[x,y],[x,y],…[x,y]],因为这实际上是一个嵌套散列。然而,令我惊讶的是,这导致所有主要浏览器的速度都降低了约15%(不包括数组创建时间)。下面是我设置的一个小测试: var points = 250000,

我基本上想做的是将一组数据点实时映射到WebGL顶点缓冲区(Float32Array)(处理动画参数化曲面)。我假设使用Float32Array(每个组件[xx…x,yy…y]一个Float32Array或交错它们:xyxy…xy)来表示数据点应该比将它们存储在点数组中更快:[[x,y],[x,y],…[x,y]],因为这实际上是一个嵌套散列。然而,令我惊讶的是,这导致所有主要浏览器的速度都降低了约15%(不包括数组创建时间)。下面是我设置的一个小测试:

var points = 250000, iters = 100;

function map_2a(x, y) {return Math.sin(x) + y;}
var output = new Float32Array(3 * points);

// generate data
var data = [];      
for (var i = 0; i < points; i++)
    data[i] = [Math.random(), Math.random()];
// run
console.time('native');
(function() {
    for (var iter = 0; iter < iters; iter++)
        for (var i = 0, to = 0; i < points; i++, to += 3) {
            output[to] = data[i][0];
            output[to + 1] = data[i][1];
            output[to + 2] = map_2a(data[i][0], data[i][1]);
        }
}());
console.timeEnd('native');

// generate data
var data = [new Float32Array(points), new Float32Array(points)];
for (var i = 0; i < points; i++) {
    data[0][i] = Math.random();
    data[1][i] = Math.random();
}
// run
console.time('typed');
(function() {
    for (var iter = 0; iter < iters; iter++)
        for (var i = 0, to = 0; i < points; i++, to += 3) {
            output[to] = data[0][i];
            output[to + 1] = data[1][i];
            output[to + 2] = map_2a(data[0][i], data[1][i]);
        }
}());
console.timeEnd('typed');
var点=250000,iters=100;
函数映射_2a(x,y){返回数学sin(x)+y;}
var输出=新阵列(3*点);
//生成数据
var数据=[];
对于(变量i=0;i

有什么我做错了吗?

我想你的问题是你没有比较相同的代码。在第一个示例中,您有一个大数组,其中填充了非常小的数组。在第二个示例中,您有两个非常大的数组,它们都需要索引。配置文件是不同的

如果我将第一个示例构造得更像第二个示例(两个大型通用数组),那么
Float32Array
实现远远优于通用数组实现


下面是一个示例。在V8中,变量可以有SMI(int31/int32)、double和pointer类型。所以我想当你用浮点数操作时,它应该转换成双精度类型。如果您使用常用数组,它已经转换为双精度。

这与您的问题无关,但您应该避免在主循环中进行乘法运算。相反,在内部循环之前将一个额外的变量初始化为0,并在每个内部循环块的末尾执行
+=3
。确保将每个变量都放在它自己的上下文中,以便变量重新声明不会引起问题。包装每个测试,在
(function(){/*…test…*/})(
的内部留出前3行。
您没有提到您正在使用什么来基准这些测试。确保使用,并确保仅包含
//运行
区域内的代码。没有理由假设Math.random()是常数时间。@JosephLennox是的,我曾经声明过一个特殊的测试函数,只将运行部分放在其中,但我认为这与此无关。感谢console.time,我们发明了一辆小自行车代替了它。虽然公平地说,结果并不一致。对于非类型化阵列,我的速度要慢6%到20%。而且,对于较小尺寸的阵列,我发现通用阵列在Chrome中的性能仍然略高于普通阵列。对于你所给的
分数
,似乎最好是本地人。向上提升一个数量级,本机数组会更好。当数组的大小再高一个数量级(25000000)时,本机数组会破坏通用数组。迭代次数似乎也很重要。一次通过,本机实现就会将其粉碎。100次通过,结果更接近。这会告诉我,从两个数组读取的性能更接近,但写入数组是实际的性能节省。是的,配置文件确实不同,但每个配置文件似乎都以一种给定数据类型的自然方式实现了相同的目标。无论如何,谢谢你的见解!