📜 ⬆️ ⬇️

JavaScript optimization: Scope, Low level ES vs ES5 Array methods

Today we will test 2 blocks of code that perform the following operation:
Given an array, you must select all items, degree 2 of which is greater than 5.

In the blue corner, Option A: Low-level code - old and scary (partially optimizable)
  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 ) ; } }

In the red corner Option B: High-level code - young and beautiful (not amenable to partial optimization)
  1. a. map ( function ( t ) { return t * t } ) . filter ( function ( t ) { return t > 5 } ) ;

Battles will take place in 3 arenas.
1. AO args - Parameters of the function activation object.
2. AO - Local variables of the function activation object.
3. Global - Global Variables.


')
In the arsenal we have the latest stable versions of all popular browsers.

All test code:
  1. // * * * * * * * * * * * * * * * * *
  2. // Activation object Arguments scope
  3. // * * * * * * * * * * * * * * * * *
  4. ( function ( a , dt , index , i , c , r , t , res ) {
  5. r = [ ] ;
  6. c = a. length ;
  7. dt = new Date ( ) ;
  8. index = 20000 ;
  9. while ( index - ) {
  10. a. map ( function ( t ) { return t * t } ) . filter ( function ( t ) { return t > 5 } ) ;
  11. }
  12. r [ 0 ] = ( new Date ( ) - dt ) ;
  13. dt = new Date ( ) ;
  14. index = 20000 ;
  15. while ( index - ) {
  16. for ( i = 0 , res = [ ] ; i < c ; i ++ ) {
  17. t = a [ i ] ;
  18. if ( t > = 2.236067 ) {
  19. continue ;
  20. } else {
  21. res. push ( t * t ) ;
  22. }
  23. }
  24. }
  25. r [ 1 ] = ( new Date ( ) - 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. // Activation object scope
  30. // * * * * * * * * * * * * * * * * *
  31. ( function ( ) {
  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. index ,
  35. i ,
  36. c ,
  37. r ,
  38. t ,
  39. res
  40. ;
  41. r = [ ] ;
  42. c = a. length ;
  43. dt = new Date ( ) ;
  44. index = 20000 ;
  45. while ( index - ) {
  46. a. map ( function ( t ) { return t * t } ) . filter ( function ( t ) { return t > 5 } ) ;
  47. }
  48. r [ 0 ] = ( new Date ( ) - dt ) ;
  49. dt = new Date ( ) ;
  50. index = 20000 ;
  51. while ( index - ) {
  52. for ( i = 0 , res = [ ] ; i < c ; i ++ ) {
  53. t = a [ i ] ;
  54. if ( t > = 2.236067 ) {
  55. continue ;
  56. } else {
  57. res. push ( t * t ) ;
  58. }
  59. }
  60. }
  61. r [ 1 ] = ( new Date ( ) - dt ) ;
  62. alert ( 'ao:' + r ) ;
  63. } ( ) ) ;
  64. // * * * * * * * * * * * * * * * * *
  65. // Global scope
  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. index ,
  70. i ,
  71. c ,
  72. r ,
  73. t ,
  74. res
  75. ;
  76. r = [ ] ;
  77. c = a. length ;
  78. dt = new Date ( ) ;
  79. index = 20000 ;
  80. while ( index - ) {
  81. a. map ( function ( t ) { return t * t } ) . filter ( function ( t ) { return t > 5 } ) ;
  82. }
  83. r [ 0 ] = ( new Date ( ) - dt ) ;
  84. dt = new Date ( ) ;
  85. index = 20000 ;
  86. while ( index - ) {
  87. for ( i = 0 , res = [ ] ; i < c ; i ++ ) {
  88. t = a [ i ] ;
  89. if ( t > = 2.236067 ) {
  90. continue ;
  91. } else {
  92. res. push ( t * t ) ;
  93. }
  94. }
  95. }
  96. r [ 1 ] = ( new Date ( ) - dt ) ;
  97. alert ( 'global:' + r ) ;


Code: pastebin.com/mqBdkXZG

results


FFhigh levellow level
Ao args45892
AO474122
Global479162
Operahigh levellow level
Ao args41622
AO42721
Global42849
Chromehigh levellow level
Ao args839
AO89eight
Global9828
Sahigh levellow level
Ao args15321
AO14624
Global14725
IE8high levellow level
Ao argsdropped out441
AOdropped out393
Globaldropped out822

Results


As you can see, there is a trend AO args | AO faster Global. This is clear from the ECMAScript specification - accessing the variables of the activation object is faster because it (JSC) is “closer to the code” than the global object.
Low-level code, many times faster than the full-level one because ECMAScript does not have blocks like in Ruby, a function is called for each element of the array, and a function call is a costly operation for JS. High level code slower up to 20 times!
Chrome is so fast because it has a JIT compilation, but for frequently used blocks of code (1 run will give the same result).
An interesting point shows Firefox: AO args (low) 92; AO (low) 122; AO args a quarter faster. Although all these variables that AO args, that AO lie in one object, but in FF AO args, judging by the results, are allocated in a separate object.

Another interesting test.
  1. ( function ( r , dt , index , i , j ) {
  2. dt = new Date ( ) ;
  3. index = 50000 ;
  4. while ( index - ) {
  5. // Block A
  6. for ( i = 0 , j = 0 ; i < 20 ; i ++ ) {
  7. j ++;
  8. }
  9. // -------
  10. }
  11. r [ 0 ] = new Date - dt ;
  12. dt = new Date ( ) ;
  13. index = 50000 ;
  14. while ( index - ) {
  15. // Block 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 ] = new Date - dt ;
  24. alert ( r ) ;
  25. } ( [ ] ) ) ;


Which unit will be faster? Answer: pastebin.com/hXxQb6pk

UPD In the end, everything comes down to the interface redrawing (reflow, redraw), however, as my practice has shown, reflow optimization was not enough. Calls of anonymous functions ate a significant part, eliminating them received a good increase, especially in ancient browsers, which is why we suffer. Do not take this article as a guide to action, write the code as you see fit for you. I advise you to optimize as needed.

Source: https://habr.com/ru/post/110391/


All Articles