为什么使用 for 比 some() 或 filter() 快 [英] Why using for is faster than some() or filter()

查看:29
本文介绍了为什么使用 for 比 some() 或 filter() 快的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试了两种不同的方式来做某事,但我对性能结果感到惊讶:

I tried two different way to do something and I am surprised by the performance result :

我有两个版本的函数:

使用 for :

$scope.hasBlockResult = function (IS, area, block) {
    if (!block)
        return false;
    for (var i = 0; i < $scope.filteredCartoList.length; i++) {
        if ($scope.filteredCartoList[i].informationSystem === IS 
            && $scope.filteredCartoList[i].area === area 
            && $scope.filteredCartoList[i].block === block)
            return true;
    }
    return false;
};

并使用 some() 函数:

$scope.hasBlockResult = function (IS, area, block) {
    if (!block)
        return false;

    return ($scope.filteredCartoList.some(function (carto) {
        if (carto.informationSystem === IS && carto.area === area && carto.block === block)
            return true;
        return false;
    }));
};

同样的事情:

for 之间:

for (var i = 0; i < $scope.filteredCartoList.length; i++) {
    if ($scope.filteredCartoList[i].informationSystem == IS 
        && $scope.filteredCartoList[i].type != 'AM' 
        && $scope.filteredCartoList[i].type != 'IF' 
        && $scope.filteredCartoList[i].area == area 
        && $scope.filteredCartoList[i].block == block)
        $scope.resultList.push($scope.filteredCartoList[i]);
    }

filter() :

$scope.resultList = $scope.filteredCartoList.filter(function (carto) {
    if (carto.informationSystem == IS 
        && carto.type != 'AM' 
        && carto.type != 'IF' 
        && carto.area == area 
        && carto.block == block)
        return true;
    return false;
});

我希望 filter()some() 方法比 for 方法更快,但在这两种情况下,根据对于 angularjs batarang 性能选项卡,for 更快.​​

I expected the filter() and the some() methods to be faster than the for method, but in both case, according to angularjs batarang performance tab, the foris faster.

推荐答案

我查看了 基准您在评论中发帖.这些基准测试存在一些缺陷:

I took a look at the benchmarksyou posted in the comments. These benchmarks have a few flaws:

  • 循环示例在基准测试本身中使用 console.timeEndconsole.log,它们都很慢.在撰写本文时,其他示例均未执行此操作.
  • some 示例执行类型强制.
  • 所有测试都在其循环中执行字符串连接.
  • The loop example uses console.timeEnd and console.log within the benchmark itself, which are both slow. None of the other examples did this at time of writing.
  • The some example performs type coercion.
  • All of the tests are performing string concatenation within their loops.

为了从这些基准中得出任何结论,我们首先需要消除这些偏差来源.

In order to draw any conclusions from these benchmarks, we first need to eliminate these sources of bias.

以下是消除这些偏差的 8GB DDR3 i5 笔记本电脑的结果,按照最快到最慢的顺序重新排序(数字越小越好):

Here are the results on an 8GB DDR3 i5 Laptop with these biases eliminated, re-ordered in terms of fastest to slowest (lower numbers are better):

OBJECT Average 0.0010666643114139636
SEEK Average 0.00593666957380871
LOOP Average 0.008436664550875625
SOME Average 0.013993332007279
FILTER Average 0.02592999837361276

这些是可以预期的,原因如下:

These are what is to be expected, and here is why:

对象访问非常快,因为对象本质上是哈希映射.无论对象的大小如何,访问一个元素都是一个恒定的速度.

Object access is very quick because objects are essentially hash maps. Regardless of the size of the object, accessing an element will be a constant speed.

Seek 被实现为使用 indexOf 来定位一个元素,然后在直接数组索引处访问该元素.虽然执行此操作的实际方法是特定于实现的,但它与对象访问非常相似,因此速度非常快.

Seek is implemented as using indexOf to locate an element and then accessing that element at the direct array index. While the actual method of doing this is implementation-specific, it is going to be very similar to object access and thus very fast.

循环方法较慢,主要是因为与seek"测试不同,循环测试遍历整个数组并执行数组访问和对象访问.seek 方法不这样做.它在找到元素后几乎立即爆发.

The loop approach is slower primarily because unlike the 'seek' test, the loop test iterates over the entire array and does both array access AND object access. The seek method doesn't do this. It breaks out almost immediately after finding the element.

这意味着除了最坏的情况外,seek 将比 loop 快.

This means that in all except the worst cases, seek will be faster than loop.

有些具有每次迭代都要调用的函数调用的开销.此外,JIT 编译器根本无法对此进行优化,因为 JIT 编译器不知道您将向 some 传递什么.在最优化的情况下,有些充其量会执行与循环相同的操作,但由于函数调用,它总是会变慢.

Some has the overhead of a function invocation to be invoked every single iteration. In addition, this cannot be optimized at all by the JIT compiler because the JIT compiler doesn't know what you're going to pass into some. Some will, at best, perform the same as loop in the most optimized cases but because of the function invocations it will always be slower.

Filter 具有some"的所有注意事项,但它始终会遍历整个数组,而不是在单个元素处停止.因此,您应该始终期望 filter 比 for 循环慢得多 - 特别是当您考虑到 filter 还创建一个 new 数组并返回时!

Filter has all the caveats of "some", but it will always iterate over the entire array instead of halting at a single element. Due to this, you should always expect filter to be much slower than a for loop - especially when you consider that filter also creates a new array which it returns!

这篇关于为什么使用 for 比 some() 或 filter() 快的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆