I tried two different way to do something and I am surprised by the performance result :
I have 2 versions of a function :
Using a 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;
};
And using some()
function :
$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;
}));
};
Same thing here :
Between the 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]);
}
and the 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;
});
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 for
is faster.
I took a look at the benchmarksyou posted in the comments. These benchmarks have a few flaws:
console.timeEnd
and console.log
within the benchmark itself, which are both slow. None of the other examples did this at time of writing.some
example performs type coercion.In order to draw any conclusions from these benchmarks, we first need to eliminate these sources of bias.
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 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.
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.
This means that in all except the worst cases, seek will be faster than loop.
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 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!
Nothing beats native (vanilla) javascript when it comes to performance. Question boils down to "Do you want to spend time and resources in re-inventing the wheel by doing it yourself or just leveraging an external lib that does it for you?". Yes you sacrifice load time and performance but you save time and time is money. You can make your for loop faster by also caching the length of the array as such
for (var i = 0, len = $scope.filteredCartoList.length; i < len; i++)
This is going to work faster especially in IE because here you are caching the length of your $scope.filteredCartoList
instead of calculating it every iteration of the loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With