JavaScriptのArray-Likeオブジェクトにはfilterなどが用意されていない事があるので
以下の2つの方法での実行を検討してベンチマークを行いました。
Array.prototype.filter.call(obj,fn)
Array.from(obj).filter(fn)
結論
Array.prototype.filter.call
の方が早かったです.
Array.from(obj).filter
の方はArray-LikeをArrayに変換する処理が入るのでそこがボトルネックになっているのだと思います.
ただ2048字の文字列を4096回処理してこの差なので、一般的な状況では致命的な速度差にはならないと感じました(単純な文字列比較だからかもしれませんが).
ベンチマーク内容
環境
- macOS Sierra 10.12.6
- Google chrome 63.0.3239.132(Official Build) (64 ビット)
chromeを再起動後実行
コード
(function(){
function randomArrayLike(length){
let c = "abcdefghijklmnopqrstuvwxyz0123456789";
let cl = c.length;
let r = "";
for(var i=0; i<length; i++){r += c[Math.floor(Math.random()*cl)];}
return r;
}
let loop = 4096;
let length = 2048;
var junk;
let fn = function(x) {
if( x=='a' || x=='n' || x=='0'){return true}else{return false}
};
function bench_filtercall(arraylike){
for(let i=0;i<loop;i++){
let b = Array.prototype.filter.call(arraylike, fn);
junk = b.length;
}
}
function bench_fromfilter(arraylike){
for(let i=0;i<loop;i++){
let b = Array.from(arraylike).filter(fn);
junk = b.length;
}
}
let arraylike = randomArrayLike(length);
console.time('filter.call1');
bench_filtercall(arraylike);
console.timeEnd('filter.call1');
console.time('from.filter1');
bench_fromfilter(arraylike);
console.timeEnd('from.filter1');
arraylike = randomArrayLike(length);
console.time('from.filter2');
bench_fromfilter(arraylike);
console.timeEnd('from.filter2');
console.time('filter.call2');
bench_filtercall(arraylike);
console.timeEnd('filter.call2');
})();
結果
filter.call1: 669.18798828125ms
from.filter1: 1072.364013671875ms
from.filter2: 1052.09716796875ms
filter.call2: 617.71875ms
おまけ(map)
コード
(function(){
function randomArrayLike(length){
let c = "0123456789";
let cl = c.length;
let r = "";
for(var i=0; i<length; i++){r += c[Math.floor(Math.random()*cl)];}
return r;
}
let loop = 4096;
let length = 2048;
var junk;
let fn = function(x) {
return Number(x) * 2 + 3
};
function bench_mapcall(arraylike){
for(let i=0;i<loop;i++){
let b = Array.prototype.map.call(arraylike, fn);
junk = b.length;
}
}
function bench_frommap(arraylike){
for(let i=0;i<loop;i++){
let b = Array.from(arraylike).map(fn);
junk = b.length;
}
}
let arraylike = randomArrayLike(length);
console.time('map.call1');
bench_mapcall(arraylike);
console.timeEnd('map.call1');
console.time('from.map1');
bench_frommap(arraylike);
console.timeEnd('from.map1');
arraylike = randomArrayLike(length);
console.time('from.map2');
bench_frommap(arraylike);
console.timeEnd('from.map2');
console.time('map.call2');
bench_mapcall(arraylike);
console.timeEnd('map.call2');
})();
結果
map.call1: 1472.779052734375ms
from.map1: 1132.084228515625ms
from.map2: 1067.93310546875ms
map.call2: 1426.677978515625ms