web-dev-qa-db-ja.com

`array.pop()`割り当てを使用したWhileループと他のメソッドの予想されるパフォーマンスとは

最近、JavaScriptのarray.reduce()メソッドを利用するコードをリファクタリングするように依頼されました。他の開発者がコードを読みにくいと感じたためです。これを行っている間、さまざまなアプローチを検証できるように、JavaScript配列反復のパフォーマンスベンチマークを試すことにしました。配列を削減する最速の方法を知りたいのですが、最初の結果を信頼できるかどうかはわかりません。

http://jsbench.github.io/#8803598b7401b38d8d09eb7f13f0709aenter image description hereenter image description here

上記のベンチマークに(while loop array.pop()割り当て)のテストケースを追加しましたが(大部分はそれを楽しむため)、テストに問題があると思います。正確には、操作数/秒の変動は大きいようです。この方法の方がはるかに高速になる理由がわからないので、テストケースに問題があるのではないかと心配しています。

私はこれをかなり調査し、何年にもわたって多くの矛盾する情報を見つけました。上記のリンク先のベンチマークテストで測定された高い分散を引き起こしている特異性をよりよく理解したいと思います。これがこの投稿につながります:ベンチマークの例(上記のリンクと下に表示)を考えると、Whileループのテストケースは、Forループのテストケースよりも5000倍以上速く測定されるのはなぜですか?

//Benchmark Setup
var arr = [];
var sum = 0; //set to 0 before each test
for (var i = 0; i < 1000; i++) {
  arr[i] = Math.random();
}
// Test Case #1
// While loop, implicit comparison, inline pop code
var i = array.length; 
while ( i-- ) {
    sum += array.pop();
}
// Test Case #2
// Reverse loop, implicit comparison, inline code
for ( var i = arr.length; i--; ) {
    sum += arr[i];
}

*編集済み

反対票に応えて。この投稿を参考にしてください。リンクのコンテキストを提供するために画像を追加しています。不要な詳細を削除し、内容を調整して、回答を求めている質問に焦点を当てました。混乱していた前の例も削除しました。

3
Kenneth Moore

現在のテストフレームワークで、合計を行う前に配列をコピーして遊んでいることに気付きました。私はこれを自分で試したところ、この変更によりpop()のパフォーマンス上の利点が失われました。実際には、配列のインデックス付けバージョンよりも低速です。配列インデックス作成ソリューションは、この変更による影響を受けていないようです。

これは、ここで何が起こっているかについての手掛かりを与えると思います。セットアップ機能はテスト機能と合わせて最適化されていると思います。セットアップ時間はパフォーマンステストの一部であることに気づきました。たとえば、console.log呼び出しをセットアップに入れると、1秒あたりのテスト操作が劇的に減少します。

配列を作成してすべての要素をポップすると、空の配列が残ります。発生している可能性が高いのは、オプティマイザが配列が無関係であると判断し、それを排除するか、少なくとも値で埋めることを排除することです。その後、関数は単純に数値を追加するループになります。それはさらにそれを最適化しているかもしれません。したがって、この実験は興味深いものですが、実際の問題にはほとんど影響しません。

2
JimmyJames