sayingにもあるように、何かをうまくやりたいのであれば、自分でそれをしてください。
私はまず、最新の主要なブラウザーでさまざまな言語構成(最も基本的なものから始まる)の速度をテストし、パフォーマンスを要求するスクリプトで何をどのように使用するかについてのこの結論に基づいてテストすることにしました。
さて、結果が得られたので、一般的な使用のためにそれらを出してみませんか?
Upd: deerua habraiserが提供する結果のグラフを追加しました(表形式よりも情報の視覚的提示をよりよく知覚する人向け)
はじめに
したがって、テストマシンはP4 3GHz(デュアルコア)、1.5RAM、Vista 32ビットです。
一連のブラウザ-FF3、Opera 9.62、Chrom 1.0、IE7、IE8b2
IE8はオリジナルではなく、 IETesterプログラムを通じて立ち上げられたとすぐに言います
オリジナルとどれだけ一致するかはわかりませんが、少なくともIE7では、結果は非常に強く、方向が異なります。
誰かがIE6または他のブラウザをテストしたい場合-実際に歓迎します)
試験方法
以下で説明するすべての言語構成要素は、ループで100万回繰り返すことでテストされました。 特定の平均結果を明らかにするために、このアクションを各ブラウザーで数回繰り返しました(通常、現在のシステム負荷に応じて+ -2-5%の間で変動します)。 平均結果(ミリ秒単位)がテーブルに書き込まれました。
どこでも(特に明記されていない限り)、反転されたforループが最速として使用されました(var i = 1000000; i--;)。
ビジネスに取り掛かろう
サイクル
テスト/ブラウザ | Ff3 | オペラ | クロム | IE7 | IE8b2 |
サイクル | |||||
クラシックサイクル | 71 | 100 | 16 | 238 | 218 |
反転サイクル | 34 | 34 | 7 | 70 | 118 |
whileループ | 30 | 33 | 7 | 70 | 118 |
そこで、まず最初に、ループ自体をテストすることにしました(実行可能コードが含まれていない空のループのみ)。 なぜなら 私たちのテストの基礎を言う)
サイクルについてはすでに多くのことが書かれているため、結果は非常に予測可能です。
ご覧のとおり、反転forループ(var i = 1000000; i--;)は、従来のfor(var i = 0; i <1000000; i ++)の2倍以上の速度であり、これがさらなるテストで使用された理由です。
また、サイクルが実際に同じ構造であるため、サイクルの速度は実際には逆の場合と変わらないことに気付くことができます(作業の論理によると)。
配列とオブジェクトを操作する
テスト/ブラウザ | Ff3 | オペラ | クロム | IE7 | IE8b2 |
配列とオブジェクトの繰り返し | |||||
インデックスによる大きな配列(1M)の値の取得(完全な列挙の逆順) | 430 | 170 | 18 | 790 | 1020 |
インデックスによる小さな配列(100)の値の取得 | 124 | 146 | 18 | 428 | 515 |
オブジェクトのFor-inループ(1M) | 2020年 | 2160 | 385 | 39400 | 35,400 |
逆ループでオブジェクト(1M)を反復処理する | 390 | 170 | 18 | 745 | 746 |
配列とオブジェクトの入力 | |||||
array.lengthで配列を埋める(1M) | 190 | 485 | 82 | 2640 | 865 |
ループのステップ(クラシックループ)の値を介して直接順序で配列を埋める(1M) | 200 | 432 | 75 | 2500 | 760 |
サイクルステップ(反転サイクル)の値を逆順で配列に埋める(1M) | 1180 | 310 | 124 | 2270 | 2260 |
push()による配列の充填(1M) | 176 | 1120 | 98 | 4450 | 1186 |
サイクルステップ(クラシックサイクル)の値を介して直接順序でオブジェクト(1M)を埋める | 1080 | 368 | 74 | 2400 | 2205 |
この部分は、配列と代替オブジェクトの操作に専念しています。 このテストの代替オブジェクトとは、配列の置換としてのみ使用される(つまり、配列の要素以外のプロパティを含まない)オブジェクト(Object型)を意味します。 私はそのような代替品のスピードに興味がありました。
配列(またはオブジェクト)1M-要素数がそれぞれ1,000,000、ウェル、およびインデックス(キー)が0〜100万(より正確には999999)の配列(またはその代替)を意味します。
最初のテストでは、このような配列を逆ループで完全に反復します。 このようなもの:
var a = 0;
for(var i = 1000000; i--;){a = big_array [i];}
2番目のテストでは、ループを100万回繰り返しますが、各ステップで小さな配列(サイズが100要素)から同じ値を取得します。 このテストでは、配列のサイズが値を取得する速度にどの程度影響するかを確認しました。
テストが示したように、Chromeを除くすべてのブラウザーで、配列内の値の検索時間は、要素の数の増加とともに大幅に増加する可能性があります。
3番目のテストでは、配列置換オブジェクトで完全なfor-inループが作成されます。
for-inループはすべてのブラウザで非常に遅く(inverted forに比べて)、IEでは大量のデータに対して非常に遅いことがはっきりとわかります。 forループを回避できる配列またはオブジェクトの反復には使用しないでください(つまり、キーは数字で順序付けされています)。
4番目のテストは、big_arrayが配列ではなくオブジェクトであることを除いて、最初のテストに完全に類似しています。
ループを通過する速度は、配列または代替オブジェクトのどちらを持っているかにわずかにしか依存しないことがわかります。 具体的な違いはIE8のみですが、まだベータ版であるため、すべてが変更される可能性があります。
また、配列要素の範囲を選択するタスクに直面している場合、条件で必要な要素を選択してループ内の配列を並べ替えるよりも、ブラウザーでarray.slice()メソッドを使用する方が数倍高速であることに注意してください。 違いは非常に明白なので、テストには含めませんでした。
配列を列挙することに加えて、多くの場合、それらを埋める必要があるため、次の5つのテストはまさにそれです。
原則として、すべてがテーブルから明確になっている必要があります。
- pushメソッドを使用した配列の入力は、配列[array.length] = valueを使用した入力と比較して、FFを除くすべてのブラウザーではるかに遅くなります。 (gelisの開発者は、明らかに、ネイティブメソッドの代わりにかさばるデザインが使用された場合、これが完全な不名誉であることを理解した唯一の開発者でした。)
- 一部のブラウザでは、配列を正順で埋めるか逆順で埋めるかが重要です。
- FFとIE8では、配列を埋める操作が特別に最適化されているため、代替オブジェクトを埋めるのがはるかに遅くなりますが、オブジェクトを埋めるのはそうではありません(配列の代わりにオブジェクトを使用して大量の同種のデータを格納するべきではないためです)。
関数、オブジェクト、変数
関数、オブジェクト、変数 | |||||
テスト/ブラウザ | Ff3 | オペラ | クロム | IE7 | IE8b2 |
現在のループ値で空の関数を呼び出す | 129 | 270 | 17 | 3100 | 860 |
オブジェクトの作成(コンストラクターを介して2つのメソッドと1つのプロパティを作成) | 2460 | 1900 | 593 | 18600 | 11700 |
オブジェクトの作成(プロトタイプから2つのメソッドとコンストラクターを介して1つのプロパティを作成) | 1260 | 636 | 64 | 7830 | 4210 |
オブジェクトのプロパティ(独自のプロパティ)を取得する | 84 | 142 | 16 | 406 | 412 |
オブジェクトのプロパティの取得(プロトタイププロパティ) | 90 | 147 | 29日 | 474 | 474 |
オブジェクトプロパティの取得(プライベートvarプロパティの取得メソッド) | 260 | 354 | 33 | 3430 | 1160 |
オブジェクトのインクリメンタルメソッドを呼び出します(これにより独自のプロパティをインクリメントします) | 326 | 460 | 60 | 3810 | 1520 |
オブジェクトの増分メソッドの呼び出し(オブジェクトを明示的に指定することにより、独自のプロパティを増分します) | 356 | 520 | 65 | 3985 | 1633 |
オブジェクトのインクリメンタルメソッドを呼び出す(プライベートvarプロパティをインクリメントする) | 412 | 370 | 38 | 3530 | 1320 |
まず、ループ内で空の関数を呼び出すことをテストしました。
var f = function(){}
for(var i = 1,000,000; i--;){f();}
ほとんどのブラウザでは、関数の呼び出しはかなり安価な操作です(完全に空のループと比較して、100万回の呼び出しごとに数百ミリ秒しか追加されません)。
ただし、IEは、いつものように、不快な驚きを提示します。 多くのラッパー関数でコードをラップするのが好きな人は、考えるべきことがあります)
遅い関数呼び出しは、関数呼び出しに関連する他のテスト(オブジェクトの作成やメソッドの呼び出しなど)に悪影響を与えるため、IEでの実行時間がさらに長くなることに注意してください。
次の2つのテストは、100万個のオブジェクトの作成に当てられます。1つの場合はすべてのメソッドがコンストラクターを介して作成され、もう1つはプロトタイプを介して作成されます。
違いは明らかだと思います。
次の3つのテストは、オブジェクトのプロパティを呼び出します:独自のプロパティ(this.prop = valueで作成)、プロトタイププロパティ、およびプライベートプロパティ(コンストラクタ関数からクロージャで作成)。 明らかに、ゲッターを介して最後のオプションを取得します。
一般的に、結果は予測可能です-オブジェクト自体のプロパティをはるかに速く取得できます。
この後に、オブジェクトのインクリメンタルメソッドを呼び出す3つのテストが続きます(つまり、呼び出しごとにオブジェクトのプロパティを1つずつ増やすメソッド)。 実際、ここでの違いは、このプロパティがどのように正確に作成されたかということです(つまり、メソッドからオブジェクトのプロパティにアクセスする速度がテストされます)。
この場合、Firefoxを除くすべての場所でプライベートプロパティの変更率が高いことがはっきりとわかりますが、そのようなプロパティは同じタイプのすべてのオブジェクトに共通であり、外部からの読み取り時間は最悪です(ゲッター経由)。
枝
枝 | |||||
テスト/ブラウザ | Ff3 | オペラ | クロム | IE7 | IE8b2 |
ifから8までのブランチを選択する | 800 | 500 | 60 | 1500 | 1460 |
スイッチを介して可能な8つのブランチを選択する | 315 | 334 | 54 | 868 | 1039 |
関数のハッシュから可能な8つのブランチを選択します | 620 | 400 | 86 | 4520 | 1820 |
この表の最初の2つのテストについてコメントする必要はないと思います。3番目のテストについて詳しく説明します。
関数ハッシュは、スイッチの動作をエミュレートするオブジェクトです。
たとえば、次のようなコードがあります。
スイッチ(a){
ケース0:b = 6 + 2; 休憩;
ケース1:b = 8 * 3; 休憩;
}
次に、関数ハッシュは次のようになります。
ハッシュ= {
'0':関数(){return 6 + 2;}、
'1':関数(){return 8 * 3;}
}
b =ハッシュ[a]();
これらの単純なアクションでは、ハッシュはスイッチよりも悪い結果を示します(関数を呼び出す必要があるため)。 ただし、とにかくスイッチから関数を呼び出す場合、ハッシュはおそらくより高速になります。
一般的なブラウザ出力
繰り返しますが、すべてが予測可能です。 Chromeは自信を持っていくつかのparsecsによってリードし、firefoxとoperaは2番目と3番目の場所を互いに共有します(さまざまな方法で異なるテストで)、最後にロバは悲しげに織りますが、ベータロバは患者が生きている可能性が高いという希望を与えます死んだ。
おわりに
最初に注意したいのは、上記のテストはすべて合成テストであり、負荷はWebアプリケーションの通常よりも大幅に高くテストされることです(たとえば、100万の値の配列を扱う必要はあまりありません)。
したがって、特別に高負荷の合成テストのように扱う価値があります-つまり 特定のスクリプトにとって何が重要で、何が重要でないかを認識してください。
一方、今日100回呼び出されているメソッドは、明日すでに1万回呼び出される可能性があるため、この問題をonめるべきではありません。 そして、何かがどこかで減速し始めた場合、少なくともどの方向に「掘る」べきかについての理解があるでしょう)