0

本 JavaScript Patterns Stoyan Stefanov で、彼は JavaScript でのループの一般的な方法は次のように主張しています。

for (i = 0, max = myarray.length; i < max; i++) {
// do something with myarray[i]
}

代わりにこのパターンを使用して最適化できます

for (i = myarray.length; i--;) {
// do something with myarray[i]
}

私はそれが面白いと思ったので、canvas でピクセル操作を行うことについてのこのブログ記事に示されているパフォーマンス集約型のループにテクニックを適用して、現実の世界でテストすることにしました。通常のコードと「最適化された」コードを比較するベンチマークは、こちらで確認できます。

興味深いのは、Opera と Firefox の両方で、最適化されていると思われるループが実際には通常のループ方法よりも遅いことです。何故ですか?

4

3 に答える 3

3

この種のマイクロ最適化の有効性は常に非常に限られています。VM の実装には、言語レベルでできることを超えた「一般的な方法」の最適化が含まれている可能性があります。

これが、マイクロ最適化が通常時間の無駄である理由です。初心者はそれらに執着する傾向があり、最終的には保守が困難で遅いコードを書くことになります。

于 2012-09-03T11:32:05.250 に答える
1

ループを最適化しようとするほとんどの方法はCからのものであり、コンパイラーがより単純でプロセッサーが次々に命令を実行するときです。

最近のプロセッサはコードの実行方法が大きく異なるため、特定の命令を最適化しても同じ効果は得られません。

Javascriptの場合、変更は非常に迅速です。インタプリタからコンパイルに移行したため、パフォーマンスに大きな違いが生じます。コンパイラはブラウザによって大きく異なり、新しいブラウザのバージョンごとに変更されるため、現在の1つのブラウザで高速なものは、明日は遅くなる可能性があります。

ループを最適化するいくつかの異なる方法をテストしましたが、現在、パフォーマンスにほとんど違いはありません:http: //jsperf.com/loopoptimisations

ただし、確かに言えることの1つは、ループを記述する通常の方法が最も一般的であるということです。そのため、すべてのコンパイラーは最適化に重点を置いています。

于 2012-09-03T12:12:14.490 に答える
1

まず、2 番目が 1 番目よりもはるかに高速であるべき理由がわかりません。ゼロとの比較と別の数値との比較の違いは、コンパイルされたコードの非常にタイトなループで違いを生む可能性があるものですが、それでもほとんどの場合、カーゴ カルトを選択する可能性があります (そうでない場合は、リチャード フェイマンのカーゴカルト サイエンスを読んでください。参照を取得します。他に何もなければ、それは良い読み物です。プログラミングで、それが役立つと仮定する本当の理由がない場合に、一度うまく機能したものをコピーする同様の傾向が数回以上あります)。

以下が遅くなることがわかりました。

for (i = 0; i < myarray.length; i++) {
// do something with myarray[i]
}

しかし、エンジンが長さチェックを巻き上げる最適化を行った場合、または長さのチェックと変数のチェックがとにかく同等のコストになるように実装されていた場合、遅くないこともわかりました。

また、それまたはあなたが提供する最初のコード例、またはおそらくその両方が、特定のスクリプトエンジンが最適化するものであることがわかります.jsでは非常に一般的なイディオムであり、本質的にループを伴うため、賢明です.スクリプト エンジンで検出して最適化しようとするもの。

しかし、そのような推測を超えて、javascript の下のレベルに到達してエンジンの実装を調べることなく、「一方が他方よりもそのエンジンでうまく機能するため、それが理由である」という以上のことを言うことはできません。あなたの結果は、答えが各エンジンで同じではないことを示唆しています (結局、あなたが期待したものにより多く対応していました)。

さて、いずれの場合も結果は互いに非常に近いことに注意してください。変更によって実際に最適化された、現在かなり人気のあるブラウザーを 1 つまたは 2 つ見つけたとしても、それでも価値がある可能性があります。

それが今まで価値があったのか、それとも単なる仮定だったのかに興味がある場合は、Netscape 2 (結局のところ、これまでで最初の JavaScript ブラウザー) のコピーを入手して、いくつかのコードを実行してアプローチをテストすることができます。その上で。

編集:その種の実験を試みる場合、もう1つは、配列の境界を1つオーバーシュートする意図的にバグのあるループを試すことです。エンジンの可能な最適化の 1 つは、アレイを歩いていることを認識し、範囲外で終了する場所を一度確認することです。もしそうなら、最終的にエラーになると、異なる結果になる可能性があります。

于 2012-09-03T11:52:34.057 に答える