この記事は、js 最適化の原則を共有するためのものです。興味のある方はぜひご覧ください。
まず第一に、他の言語とは異なり、JS の効率は JS エンジンの効率に大きく依存します。エンジン実装の長所と短所に加えて、エンジン自体もいくつかの特殊なコード パターンに対していくつかの最適化戦略を採用します。たとえば、FF、Opera、Safari の JS エンジンは、文字列連結操作 (+) を特別に最適化しています。明らかに、最大の効率を達成するには、エンジンの気質を理解し、エンジンの好みに応えるように努める必要があります。したがって、異なるエンジンでは、行われる最適化は互いに矛盾する可能性が最も高くなります。
そして、クロスブラウザー Web プログラミングを行う場合、最大の問題は IE6 (JScript 5.6) です。 hotfix がないと、JScript エンジンのガベージ コレクションのバグにより、実際のアプリケーションでのパフォーマンスが他のブラウザーと比べて桁違いに低くなってしまうためです。したがって、この状況での最適化は、実際には JScript の最適化となります。
そのため、最初の原則は IE6 (パッチ適用されていない JScript 5.6 以前) のみに最適化する !
プログラムが IE6 で許容可能なパフォーマンスに最適化されている場合、基本的に他のブラウザーでのパフォーマンスに問題はありません。
したがって、以下で説明する問題の多くは、他のエンジンではまったく異なる可能性があることに注意してください。たとえば、ループ内の文字列の結合には通常、Array.join の使用が必要であると考えられていますが、文字列が原因です。 SpiderMonkey などのエンジンの「+」操作が最適化されたため、Array.join の使用は「+」を直接使用する場合ほど効率的ではありません。しかし、IE6 を考慮すると、他のブラウザーとのこの効率の差はまったく言及する価値がありません。
JS の最適化は、他の言語の最適化と同じです。たとえば、最適化を開始してすぐに急いで実行しないでください。それは意味がありません。最適化の鍵は、依然として最も重要な場所、つまりボトルネックに焦点を当てることです。一般に、大規模なループではボトルネックが必ず発生します。これは、ループ自体にパフォーマンスの問題があるということではありませんが、ループによって潜在的なパフォーマンスの問題が急速に増幅される可能性があるということです。
したがって、2 番目の原則は、大規模なループを主な最適化オブジェクトとして取ることです。
以下の最適化原則は、大規模なループでのみ意味があります。ループ本体の外側でこのような最適化を行うことは、基本的には意味がありません。
現状、ほとんどのJSエンジンは解釈して実行されますが、解釈実行の場合、どの操作においても関数呼び出しの効率が悪くなります。さらに、過度に深いプロトタイプ継承チェーンやマルチレベル参照も効率を低下させます。 JScript では、レベル 10 参照のオーバーヘッドは、空の関数呼び出しのオーバーヘッドの約 1/2 です。どちらのオーバーヘッドも単純な演算 (四則演算など) よりもはるかに大きくなります。
3 番目の原則は、多すぎる参照レベルと不必要な複数のメソッド呼び出しを避けるように努めることです。
場合によっては、プロパティへのアクセスのように見えるものが、実際にはメソッド呼び出しであることに注意することが重要です。たとえば、すべての DOM プロパティは実際にはメソッドです。 NodeList を走査するとき、ループ条件による nodes.length へのアクセスは属性の読み取りのように見えますが、実際には関数呼び出しと同等です。さらに、IE DOM の実装では、childNodes.length は毎回内部トラバーサルによって再カウントされる必要があります。 (なんと、これは本当です! childNodes.length のアクセス時間は childNodes.length の値に比例することが測定されているからです!) これは非常に高価です。したがって、nodes.length を事前に js 変数に保存しておくと、トラバーサルのパフォーマンスが確実に向上します。
これも関数呼び出しであり、ユーザー定義関数の効率は言語組み込み関数の効率よりもはるかに低くなります。後者はエンジンのネイティブ メソッドのラッパーであり、エンジンは通常、 c、c++、java。さらに、同じ関数の場合、組み込み言語構造のコストは通常、組み込み関数呼び出しよりも効率的です。これは、前者は JS コードの解析フェーズ中に決定および最適化できるためです。
したがって、4 番目の原則は、可能な限り言語自体の構造体と組み込み関数を使用することです。
これは、高性能 String.format メソッド の例です。 String.format の従来の実装では、String.replace(regex, func) を使用します。 pattern に n 個のプレースホルダー (繰り返しのものを含む) が含まれる場合、カスタム関数 func が n 回呼び出されます。この高パフォーマンスの実装では、各形式呼び出しは Array.join 操作と String.replace(regex, string) 操作のみを実行し、どちらもカスタム関数呼び出しを行わずにエンジンの組み込みメソッドです。 2 つの組み込みメソッド呼び出しと n 回のカスタム メソッド呼び出し、これがパフォーマンスの違いです。
これも組み込み機能ですが、それでもパフォーマンスに違いがあります。たとえば、JScript の引数へのアクセス パフォーマンスは非常に低く、関数呼び出しにほぼ追いつきます。したがって、可変パラメーターを持つ単純な関数がパフォーマンスのボトルネックになる場合は、内部の変更を加え、引数にはアクセスせず、パラメーターを明示的に判断することで処理できます。
例:
Java コード
function sum() {
var = 0;
for (var i = 0; i
r += argument[i] }
return
r;}
この合計は通常、小さい数値で呼び出され、パラメーターが少ない場合のパフォーマンスの向上が期待されます。に変更された場合:
Java コード
function sum() {
switch
(arguments.length) {ケース
return 引数[0] ] + 引数[]; [ 0] + 引数[
1] + 引数[3] var r = ;
引数[i];
実際には、次のように変更すると、次のようになります。
return r;
for
(var i =r;
}
は大幅に改善されます (少なくとも 1 倍速くなります)。
最後は 5 番目の原則で、実際のアプリケーションではパフォーマンス上の最も重要な障害となることがよくあります。それは、不必要なオブジェクトの作成を最小限に抑えるです。
オブジェクト自体の作成には一定のコストがかかりますが、このコストは実際にはそれほど大きくありません。最も根本的な問題は、JScript の非常に愚かなガベージ コレクション スケジューリング アルゴリズム により、オブジェクトの数が増えると重大なパフォーマンスの低下が生じることです (Microsoft 関係者によると、複雑さは O(n^2) です)。
たとえば、私がテストで検証したところ、一般的な文字列のスプライシングの問題は、単に文字列オブジェクトを複数回作成するだけでは、実際にはパフォーマンス低下の原因にはなりません。最悪の部分は、オブジェクト作成時の不要なガベージ コレクションのオーバーヘッドです。 Array.join メソッドは中間文字列オブジェクトを作成しないため、ガベージ コレクションのオーバーヘッドが軽減されます。
したがって、大規模なオブジェクトの作成を単一のステートメントに変換できれば、そのパフォーマンスは大幅に向上します。たとえば、コードを構築してから評価することによって - 実際、PIES プロジェクトはこのアイデアに基づいて特殊な大規模オブジェクト ジェネレーターを構築しています...
さて、上記は JS 最適化の 5 つの原則ですをまとめてみました。
------------------hax のテクノロジーブログから転載 http://hax.iteye.com/blog/126859
関連する推奨事項:
js 最適化が IE6.0 で動作する (詳細な調整)_JavaScript スキル
以上がjs最適化の原則の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。