Arrays 哪些阵列在内部建模为如此之快,或者我做错了什么?

Arrays 哪些阵列在内部建模为如此之快,或者我做错了什么?,arrays,node.js,performance,v8,Arrays,Node.js,Performance,V8,我坐下来对我的实用程序库进行了性能优化:当我注意到一些意想不到的事情时:Array.indexOf(在节点10.9中)的查找速度非常快,但并不总是O(1) 这是在我的笔记本电脑上的一个10k大整数数组中找到中间元素的部分测试的打印输出 Array::indexOf x 828,360,306 ops/sec ±1.25% (87 runs sampled) Arr.indexOfElement x 133,620,554 ops/sec ±0.87% (86 runs sampl

我坐下来对我的实用程序库进行了性能优化:当我注意到一些意想不到的事情时:Array.indexOf(在节点10.9中)的查找速度非常快,但并不总是O(1)

这是在我的笔记本电脑上的一个10k大整数数组中找到中间元素的部分测试的打印输出

    Array::indexOf x 828,360,306 ops/sec ±1.25% (87 runs sampled)
    Arr.indexOfElement x 133,620,554 ops/sec ±0.87% (86 runs sampled)
    Arr.indexOfElement (no native) x 172,043 ops/sec ±0.92% (92 runs sampled)
    _.indexOf x 174,273 ops/sec ±0.87% (95 runs sampled)
Fastest is Array::indexOf
每秒8亿索引的速度很快

通过使数组变小(200个条目),它将保持相同的数目。 将阵列增加到1000k会将其速度降低到1582 ops/sec

因此,它可能会在幕后保留一个hashmap,但不会将密钥查找空间扩展到某个数字之外,然后获得线性搜索? 有人知道这是不是真的吗?这个数字是多少

或者我的代码中有错误:

const SIZE = 10000;
let intArray10k = MocData.numericArray(SIZE, MocDataType.RandomInt, 0, 100000);
let intArray100 = MocData.numericArray(100, MocDataType.RandomInt, 0, 100000);
intArray10k[SIZE/2 - 1] = -1;

function complete(suite: Benchmark.Suite) {
    console.log(chalk.green('Fastest is ' + (suite.filter('fastest') as any).map('name') + "\n"));
}
function cycle(event: any) {
    console.log(chalk.grey("\t" + String(event.target)));
}
export const suites = [ 
    new Benchmark.Suite()
    .add('Array::indexOf', function () {
        intArray10k.indexOf(-1);
    })
    .add('Arr.indexOfElement', function () {
        Arr.indexOfElement(intArray10k, -1);
    })
    .add('Arr.indexOfElement (no native)', function () {
        Test.Env.forceNotNative = true;
        Arr.indexOfElement(intArray10k, -1);
        Test.Env.forceNotNative = false;
    })
    .add('_.indexOf', function () {
        _.indexOf(intArray10k, -1);
    })
    // add listeners
    .on('cycle', function (event: any) {
        cycle(event);
    })
    .on('complete', function () {
        complete(this);
    }),
编辑:感谢@jmrk在分配值时提供的指导,以避免优化它。现在,没有1亿美元的价值,时代看起来更加合理。仅供参考,较高的拼接值是由于我将拼接掉并添加相同数量的值,以便保留阵列大小。拼接功能似乎没有进行这种优化

    Array::indexOf x 162,893 ops/sec ±2.05% (87 runs sampled)
    Arr.indexOfElement x 171,492 ops/sec ±0.82% (91 runs sampled)
    Arr.indexOfElement (no native) x 165,929 ops/sec ±1.07% (91 runs sampled)
    _.indexOf x 169,678 ops/sec ±0.84% (92 runs sampled)
最快的是Arr.INDEXOFLEment

    Array::slice x 130,022 ops/sec ±1.02% (91 runs sampled)
    Arr.slice x 131,115 ops/sec ±0.94% (91 runs sampled)
    Arr.shallowCopy x 130,130 ops/sec ±1.29% (89 runs sampled)
    Arr.slice (no native) x 52,057 ops/sec ±0.96% (91 runs sampled)
    Arr.shallowCopy (no native) x 59,676 ops/sec ±0.90% (92 runs sampled)
    _.slice x 60,078 ops/sec ±1.08% (94 runs sampled)
最快的是Arr.slice,Array::slice,Arr.shallowCopy

    Array::reverse x 18,420 ops/sec ±1.18% (90 runs sampled)
    Arr.reverse x 133,600 ops/sec ±0.74% (92 runs sampled)
    _.reverse x 18,075 ops/sec ±1.83% (85 runs sampled)
最快的是倒车

    Array::filter x 7,749 ops/sec ±10.31% (88 runs sampled)
    Arr.filter x 11,752 ops/sec ±6.92% (88 runs sampled)
    _.filter x 5,939 ops/sec ±0.64% (93 runs sampled)
最快的是Arr滤波器

    Array::forEach x 42,613 ops/sec ±34.98% (87 runs sampled)
    Arr.forEach x 126,806 ops/sec ±23.89% (91 runs sampled)
    _.forEach x 11,489 ops/sec ±1.23% (88 runs sampled)
最快的是阿弗雷赫

    Array::map x 17,592 ops/sec ±18.32% (88 runs sampled)
    Arr.map x 39,564 ops/sec ±14.55% (88 runs sampled)
    _.map x 8,419 ops/sec ±1.34% (87 runs sampled)
最快的是Arr.map

    Array::reduce x 29,784 ops/sec ±29.35% (88 runs sampled)
    Arr.reduce x 63,781 ops/sec ±18.30% (86 runs sampled)
    _.reduce x 9,444 ops/sec ±2.25% (88 runs sampled)
最快的是Arr.reduce

    Array::splice x 914,209 ops/sec ±1.42% (90 runs sampled)
    Arr.splice x 4,777,243 ops/sec ±0.78% (91 runs sampled)
    Arr.splice (no native) x 5,111,231 ops/sec ±0.90% (88 runs sampled)
最快的是Arr.splice(无本机)

最快的是阵列::拼接(1),Arr.removeAt

    Array::find x 124,197 ops/sec ±32.06% (90 runs sampled)
    Arr.find x 159,169 ops/sec ±9.55% (92 runs sampled)
    _.find x 23,077 ops/sec ±1.12% (88 runs sampled)
最快的是Arr.find

V8开发者。 当你每秒看到数以亿计的操作时,这通常意味着优化编译器丢弃了测试代码,你所测量的只是一个空循环。您可以使用命令行标志--print opt code进行检查。通常有效的解决方法是将结果分配给全局变量,如下所示:

var result;
function easily_misleading_microbenchmark() {
  result = intArray10k.indexOf(-1);
}
for (var i = 0; i < 1e6; i++) {
  easily_misleading_microbenchmark();
}
var结果;
功能轻松\u误导\u微基准(){
结果=intArray10k.indexOf(-1);
}
对于(变量i=0;i<1e6;i++){
容易误导的微基准();
}
愚弄编译器,使其认为结果用于某种用途

小心微基准点,因为它们很容易误导你得出错误的结论!:-)


通常,对于一个包含n个元素的数组,
Array.indexOf(value)
的复杂性应该是O(n)。它永远不是O(1)。(如果您的测量结果是O(1),那么无论您测量的是什么,都不是
Array.indexOf()

谢谢,所以我基本上是在优化器上放松,意识到没有使用该值而忽略它?我还必须说,V8中最新的数组优化非常好!)
var result;
function easily_misleading_microbenchmark() {
  result = intArray10k.indexOf(-1);
}
for (var i = 0; i < 1e6; i++) {
  easily_misleading_microbenchmark();
}