JavaScriptの最適化:スコープ、低レベルESとES5配列メソッド

今日は、次の操作を実行する2ブロックのコードをテストします。

配列を指定すると、次数2が5より大きいすべての要素を選択する必要があります。



青い角のオプションA:低レベルコード-古くて恐ろしい(部分的な最適化が可能)

  1. for ( i = 0 , res = [ ] ; i < c ; i ++ ) { t = a [ i ] ; if ( t >= 2.236067 ) { continue ; } else { res. push ( t * t ) ; } }



  2. for ( i = 0 , res = [ ] ; i < c ; i ++ ) { t = a [ i ] ; if ( t >= 2.236067 ) { continue ; } else { res. push ( t * t ) ; } }



  3. for ( i = 0 , res = [ ] ; i < c ; i ++ ) { t = a [ i ] ; if ( t >= 2.236067 ) { continue ; } else { res. push ( t * t ) ; } }



  4. for ( i = 0 , res = [ ] ; i < c ; i ++ ) { t = a [ i ] ; if ( t >= 2.236067 ) { continue ; } else { res. push ( t * t ) ; } }



  5. for ( i = 0 , res = [ ] ; i < c ; i ++ ) { t = a [ i ] ; if ( t >= 2.236067 ) { continue ; } else { res. push ( t * t ) ; } }



  6. for ( i = 0 , res = [ ] ; i < c ; i ++ ) { t = a [ i ] ; if ( t >= 2.236067 ) { continue ; } else { res. push ( t * t ) ; } }



  7. for ( i = 0 , res = [ ] ; i < c ; i ++ ) { t = a [ i ] ; if ( t >= 2.236067 ) { continue ; } else { res. push ( t * t ) ; } }



  8. for ( i = 0 , res = [ ] ; i < c ; i ++ ) { t = a [ i ] ; if ( t >= 2.236067 ) { continue ; } else { res. push ( t * t ) ; } }





赤いコーナーのオプションB:高レベルのコードは若くて美しい(部分的な最適化を受け入れられない)

  1. a。 map function t { return t * t } filter 関数 t { return t > 5 } ;


戦闘は3つのアリーナで行われます。

1. AO args-関数アクティブ化オブジェクトのパラメーター。

2. AO-関数アクティベーションオブジェクトのローカル変数。

3.グローバル-グローバル変数。







武器庫には、すべての一般的なブラウザの最新の安定バージョンがあります。



すべてのテストコード:

  1. // * * * * * * * * * * * * * * * * * *
  2. // Activationオブジェクトの引数スコープ
  3. // * * * * * * * * * * * * * * * * * *
  4. 関数 a dt index i c r t res {
  5. r = [ ] ;
  6. c = a。 長さ
  7. dt = 新しい日付 ;
  8. インデックス= 20000 ;
  9. while インデックス- {
  10. a。 map function t { return t * t } filter 関数 t { return t > 5 } ;
  11. }
  12. r [ 0 ] = 新しい日付 -dt ;
  13. dt = 新しい日付 ;
  14. インデックス= 20000 ;
  15. while インデックス- {
  16. for i = 0 res = [ ] ; i < c ; i ++ {
  17. t = a [ i ] ;
  18. if t > = 2.236067 {
  19. 続ける ;
  20. } else {
  21. 解像度 プッシュ t * t ;
  22. }
  23. }
  24. }
  25. r [ 1 ] = 新しい日付 -dt ;
  26. alert 'ao args:' + r ;
  27. } [ 1、2、3、4、5、6、7、8、9、10、1、2、3、4、5、6、7、8、9、10、1、2、3、4 5、6、7、8、9、10、1、2、3、4、5、6、7、8、9、10、1、2、3、4、5、6、7、8、9 10 ] )) ;
  28. // * * * * * * * * * * * * * * * * * *
  29. //アクティベーションオブジェクトのスコープ
  30. // * * * * * * * * * * * * * * * * * *
  31. 関数 {
  32. var a = [ 1、2、3、4、5、6、7、8、9、10、1、2、3、4、5、6、7、8、9、10、1、2、3 4、5、6、7、8、9、10、1、2、3、4、5、6、7、8、9、10、1、2、3、4、5、6、7、8 9、10 ]
  33. dt
  34. インデックス
  35. 私は
  36. c
  37. r
  38. t
  39. 解像度
  40. ;
  41. r = [ ] ;
  42. c = a。 長さ
  43. dt = 新しい日付 ;
  44. インデックス= 20000 ;
  45. while インデックス- {
  46. a。 map function t { return t * t } filter 関数 t { return t > 5 } ;
  47. }
  48. r [ 0 ] = 新しい日付 -dt ;
  49. dt = 新しい日付 ;
  50. インデックス= 20000 ;
  51. while インデックス- {
  52. for i = 0 res = [ ] ; i < c ; i ++ {
  53. t = a [ i ] ;
  54. if t > = 2.236067 {
  55. 続ける ;
  56. } else {
  57. 解像度 プッシュ t * t ;
  58. }
  59. }
  60. }
  61. r [ 1 ] = 新しい日付 -dt ;
  62. alert 'ao:' + r ;
  63. } ;
  64. // * * * * * * * * * * * * * * * * * *
  65. //グローバルスコープ
  66. // * * * * * * * * * * * * * * * * * *
  67. var a = [ 1、2、3、4、5、6、7、8、9、10、1、2、3、4、5、6、7、8、9、10、1、2、3 4、5、6、7、8、9、10、1、2、3、4、5、6、7、8、9、10、1、2、3、4、5、6、7、8 9、10 ]
  68. dt
  69. インデックス
  70. 私は
  71. c
  72. r
  73. t
  74. 解像度
  75. ;
  76. r = [ ] ;
  77. c = a。 長さ
  78. dt = 新しい日付 ;
  79. インデックス= 20000 ;
  80. while インデックス- {
  81. a。 map function t { return t * t } filter 関数 t { return t > 5 } ;
  82. }
  83. r [ 0 ] = 新しい日付 -dt ;
  84. dt = 新しい日付 ;
  85. インデックス= 20000 ;
  86. while インデックス- {
  87. for i = 0 res = [ ] ; i < c ; i ++ {
  88. t = a [ i ] ;
  89. if t > = 2.236067 {
  90. 続ける ;
  91. } else {
  92. 解像度 プッシュ t * t ;
  93. }
  94. }
  95. }
  96. r [ 1 ] = 新しい日付 -dt ;
  97. alert 'global:' + r ;




コード: pastebin.com/mqBdkXZG



結果



Ff 高レベル 低レベル
AO args 458 92
あお 474 122
グローバル 479 162
オペラ 高レベル 低レベル
AO args 416 22
あお 427 21
グローバル 428 49
クロム 高レベル 低レベル
AO args 83 9
あお 89 8
グローバル 98 28
高レベル 低レベル
AO args 153 21
あお 146 24
グローバル 147 25
IE8 高レベル 低レベル
AO args 脱落した 441
あお 脱落した 393
グローバル 脱落した 822


まとめ



ご覧のとおり、トレンドはAO args | AOがGlobalよりも速いです。 これはECMAScript仕様から明らかです。アクティベーションオブジェクトの変数へのアクセスは、グローバルオブジェクトよりも「コードに近い」ため(AO)高速です。

ECMAScriptにはRubyのようなブロックがないため、配列の各要素に対して関数が呼び出され、関数の呼び出しはJSにとって高価な操作であるため、低レベルコードは高レベルコードよりも何倍も高速です。 高レベルのコードは最大20倍遅くなります!

ChromeはJITコンパイルを備えているため非常に高速ですが、頻繁に使用されるコードブロックについては(1回の実行で同じ結果が得られます)。

興味深い点は、Firefoxを示しています。AOargs(低)92; AO(低)122; AOは4分の1の速さで議論します。 これらの変数はすべてAO引数ですが、AOは同じオブジェクト内にありますが、AF AO引数では、結果から判断して、別のオブジェクトとして割り当てられます。



別の興味深いテスト。

  1. function r dt index i j {
  2. dt = 新しい日付 ;
  3. インデックス= 50000 ;
  4. while インデックス- {
  5. //ブロックA
  6. for i = 0 j = 0 ; i < 20 ; i ++ {
  7. j ++;
  8. }
  9. // -------
  10. }
  11. r [ 0 ] = 新しい日付-dt ;
  12. dt = 新しい日付 ;
  13. インデックス= 50000 ;
  14. while インデックス- {
  15. //ブロックB
  16. j 0 です。
  17. j ++; j ++; j ++; j ++; j ++;
  18. j ++; j ++; j ++; j ++; j ++;
  19. j ++; j ++; j ++; j ++; j ++;
  20. j ++; j ++; j ++; j ++; j ++;
  21. // -------
  22. }
  23. r [ 1 ] = 新しい日付-dt ;
  24. アラート r ;
  25. } [ ] ;




どのブロックが高速になりますか? 回答: pastebin.com/hXxQb6pk



UPD最終的には、すべてがインターフェイスの再描画(リフロー、リドロー)に依存しますが、私の実践が示しているように、リフローの最適化は十分ではありませんでした。 匿名関数の呼び出しによってかなりの部分が消費され、それらが削除され、特に古代のブラウザではかなりの増加が得られました。 この記事を行動の手引きとして受け取らないでください。あなたにとって便利だと思うコードを書いてください。 必要に応じて最適化することをお勧めします。



All Articles