LoginSignup
4
3

More than 3 years have passed since last update.

JSのArray.prototype.filter.callとArray.from().filterどっちが早いか

Last updated at Posted at 2018-01-18

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
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3