初心者向けのデッドコードの削除

翻訳者から:残念ながら、ブラウザ開発者からの次の投稿がIE9対SunSpiderについて翻訳するのを待たずに、自分で翻訳しなければなりませんでした。 別の理由 リフレクション用の情報のみを提供した他の( firstsecond )とは異なり、これは実用的な知識を提供します-すべての開発者が新しいIE9でコードを起動するときに遭遇する落とし穴の説明。



Dean Hachamovitch:新しいJavaScriptエンジン(コードネームChakra)の変更点の1つは、実際のサイトのパフォーマンスを向上させるためのデッドコード破壊です[ 1 ]




昨日、IE9のデッドコード除去アルゴリズムを簡単に分析した後、バグを送信しました。 その後、IE9チームはプラットフォームプレビュー7をリリースし、IEに関するブログを更新しました。



デッドコードを削除することは正当な最適化ですが、非常に簡単に表面的な実装を行うと、予期しない動作が発生し、エラーの原因になる可能性があります。





IE9で実装されたアルゴリズムの脆弱性に関して、私たちの調査では、次の操作のみを最適化できることが示されました:-、+、++、<<、+ =、-=、およびif(>)。 たとえば、 そのテストでこの比較を変更した場合:



  if(TargetAngle> CurrAngle){ 






  if(TargetAngle <= CurrAngle){ 


IE9はこのコードを削除しなくなります。 IE9の開発者が、乗算や除算などのリソースを大量に消費する操作を削除しないことにしたのは興味深いです。 最適化のために選択された一連の操作は、SunSpiderの数学テストで使用された操作と一致するようです。



妥当性に関しては、IE9でのデッドコード除去の実装でいくつかの問題が既に発見されています。 開発者の1人であるAndreas Galは、最初に触れる開発者に注目しました。 IEブログの学部長は例を挙げました:



次の例では、ループ内のコードが常に同じ変数を上書きするため( CSではこれはデッドセーブと呼ばれます)、このコードは1回の呼び出しに単純化できます。



関数func(a、b){
    var x;
    var i = 300;
    while(i--){
       x = a + b;  //デッドストア
    }
 }




この例では、Deanはxが常に書き換えられているため、すべての呼び出しがxに同じ値を与えるため、JavaScriptエンジンはループを1回だけ実行して時間を節約できることを示しようとしています。



これはC#などの静的型付き言語に当てはまる場合がありますが、残念ながらJavaScriptには当てはまりません。



この関数は、次のように呼び出されると最適化できます。



  func(1,2) 


副作用がないので。 ただし、このような関数を呼び出すと、最適化できなくなります。



  func(1、{valueOf:function(){alert( "Hi Dean!"); return 2;}}); 


ここでは、オブジェクトを2番目の引数(b)として渡し、その中で、オペレーションa + bによって呼び出されるvalueOfメソッドを宣言します。 予期せぬターン? 言語のこの動的な側面により、JavaScriptの最適化が非常に難しくなります。また、デッドコードの削除やデッドセーブの削除など、コンパイラに従来の最適化を追加するタスクは、些細ではありませんが何かになります。



IE9 Platform Preview#7は、ブログのこの例を正しく処理しません( 試すことができます)。 valueOfメソッドの独自の実装を持つオブジェクトで関数が呼び出された場合、IE9はこのハンドラーを誤って呼び出しません。



JavaScriptの詳細なデッドコード分析は実際には非常に複雑であり、プログラム全体のグローバルな分析が必要です。 IE9ブログでは、配列のローカルリテラル操作を副作用がないため、デッドコードのように単純化できる方法について説明しています。 したがって、次の呼び出しを安全に削除できると想定できます。



  func(1、[1,2,3,4,5]) 


最初の引数は定数であり、配列のリテラルは非常に安全に見えます。 残念ながら、プログラムでこの呼び出しの前に次のコードが実行された場合、この削除は再び表面的なものになります。



  Object.prototype.valueOf = function(){alert( "IE9 is fast!");  } 


ここでは、リテラルを含むすべてのオブジェクトのvalueOfハンドラーを再定義しているため、a + bを追加すると、valueOfの実装が呼び出されます。 繰り返しになりますが、IE9はハンドラーの呼び出しを誤って見逃します。この場合、他のファイルのコードが既に「最適化」に影響を与える可能性があるため、このケースを判別するのはさらに困難です。



私が説明する2番目の表面実装の問題は、別のMozilla開発者であるChris Learyによって気づかれました。 IE9がデッドコードとして削除する数学テストのループは、グローバル変数「Angles」で機能します。 Angles変数の定義がソースから削除された場合でも、IE9はまだcordicsincos()呼び出しを削除することがわかりました。 この場合、「角度」はどこにも定義されていないため、正しい動作はReferenceError例外をスローすることです。 必要に応じて、 このデモを試してエラーを確認してください。 さらに、Angles変数またはウィンドウオブジェクトのゲッターなどの新しいES5機能の使用を開始すると、IE9のデッドコード削除アルゴリズムにさらに多くの問題が見つかります。



私の投稿の時間がIE9 PP7のリリースと一致したという事実はまったくの偶然であり、すべてのブラウザーがJavaScriptをより高速に実行できることを嬉しく思います。 しかし、前述のように、IE9でのデッドコードの削除の実装は、幅広いアクションの深刻な最適化と見なすことはできないと思います。 彼女はSunSpiderテスト以外ではテストされていないようです。



明らかに、何かを見逃していた可能性があるため、明日午前中にIEチームからのTwitter Q&Aセッションにさらに多くの情報が表示されるはずです。



翻訳者から: のコメントでは、グローバルな分析の代わりに、これらの問題に対する代替の安価なソリューションが提供されています。 IE9開発者がこれらの問題を修正し、SunSpider開発者がテストに副作用を追加することを願っています。 この優れた分析へのリンク提供してくれたXPilotに感謝します。



All Articles