Angular: Tuning The Engine

Angular: Tuning The Engine

Dive into the Angular event loop, how the $digest cycle works and performance tuning tips and tricks.

B56bb22b3a4b83c6b534b4c114671380?s=128

Todd Motto

March 15, 2016
Tweet

Transcript

  1. None
  2. ANGULAR TUNING THE ENGINE

  3. WHAT IS THIS TALK ABOUT? Angular event loop Understand the

    $digest cycle Performance tuning
  4. ANGULAR EVENT LOOP

  5. Browser

  6. Browser Event Queue

  7. Browser Event Queue click change focus

  8. Browser Event Queue click change focus JavaScript

  9. Browser Event Queue click change focus JavaScript Angular $apply(fn);

  10. Browser Event Queue click change focus JavaScript Angular $apply(fn); fn();

  11. Browser Event Queue click change focus JavaScript Angular $apply(fn); fn();

    $digest
  12. Browser Event Queue click change focus JavaScript Angular $apply(fn); fn();

    $digest DOM Render
  13. Input value:

  14. < i n p u t n g - m

    o d e l = " t i t l e " > < d i v > I n p u t v a l u e : < s p a n > { { t i t l e } } < / s p a n > < / d i v >
  15. $rootScope and $scopes $$watchers $scope.$watch $digest loop $DIGEST CYCLE

  16. $ROOTSCOPE AND $SCOPES

  17. $rootScope

  18. $rootScope Parent $scope

  19. $rootScope Parent $scope Child $scope Child $scope

  20. $rootScope (ng-app) Parent $scope Child $scope Child $scope

  21. $rootScope Parent $scope Child $scope (ng-app) (ng-controller) Child $scope

  22. $rootScope Parent $scope Child $scope (ng-app) (ng-controller) Child $scope (ng-repeat)

    (ng-repeat)
  23. THESE "SCOPES" ARE JUST OBJECTS THAT INHERIT FROM EACHOTHER

  24. EACH "SCOPE" HAS A "$$WATCHERS" PROPERTY

  25. $rootScope Parent $scope Child $scope $$watchers: null $$watchers: null Child

    $scope $$watchers: null $$watchers: null
  26. $rootScope Parent $scope Child $scope $$watchers: null $$watchers: [{...}] Child

    $scope $$watchers: [{...}] $$watchers: [{...}]
  27. S c o p e { $ $ w a

    t c h e r s : [ { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { } , g e t : f u n c t i o n ( ) { } , l a s t : ' T o d d ' } ] }
  28. $SCOPE.$WATCH

  29. f u n c t i o n M a

    i n C o n t r o l l e r ( $ s c o p e ) { $ s c o p e . n a m e = ' T o d d ' ; $ s c o p e . $ w a t c h ( ' n a m e ' , f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { / / d o s o m e t h i n g w i t h n e w V a l u e } ) ; } a n g u l a r . m o d u l e ( ' a p p ' ) . c o n t r o l l e r ( ' M a i n C o n t r o l l e r ' , M a i n C o n t r o l l e r ) ;
  30. S c o p e { $ $ w a

    t c h e r s : [ { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { } , g e t : f u n c t i o n ( ) { } , l a s t : ' T o d d ' } ] }
  31. VIEW INTERPOLATION

  32. f u n c t i o n M a

    i n C o n t r o l l e r ( $ s c o p e ) { $ s c o p e . n a m e = ' T o d d ' ; } a n g u l a r . m o d u l e ( ' a p p ' ) . c o n t r o l l e r ( ' M a i n C o n t r o l l e r ' , M a i n C o n t r o l l e r ) ;
  33. < ! - - T H I S c r

    e a t e s t h e " w a t c h e r " - - > < p > { { n a m e } } < / p >
  34. S c o p e { $ $ w a

    t c h e r s : [ { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { } , g e t : f u n c t i o n ( ) { } , l a s t : ' T o d d ' } ] }
  35. WHY IS THIS IMPORTANT TO KNOW?

  36. Angular uses $$watchers to update the DOM Angular uses $$watchers

    to sync our Model $$watchers impact performance $$WATCHERS ARE WHAT DRIVES ANGULAR
  37. INPUT AND INTERPOLATION EXAMPLE

  38. Input value:

  39. < i n p u t n g - m

    o d e l = " t i t l e " > < d i v > I n p u t v a l u e : < s p a n > { { t i t l e } } < / s p a n > < / d i v >
  40. NGMODEL INTERNALS v a r i n p u t

    = d o c u m e n t . q u e r y S e l e c t o r ( ' i n p u t ' ) ; i n p u t . a d d E v e n t L i s t e n e r ( ' i n p u t ' , f u n c t i o n ( ) { $ s c o p e . $ a p p l y ( f u n c t i o n ( ) { $ s c o p e . t i t l e = t h i s . v a l u e ; } ) ; } , f a l s e ) ;
  41. NGMODEL CREATES A $$WATCHER $ s c o p e

    . $ w a t c h ( ' t i t l e ' , f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { d o c u m e n t . q u e r y S e l e c t o r ( ' i n p u t ' ) . v a l u e = n e w V a l u e ; } ) ; INTERPOLATION $$WATCHER $ s c o p e . $ w a t c h ( ' t i t l e ' , f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { d o c u m e n t . q u e r y S e l e c t o r ( ' s p a n ' ) . i n n e r H T M L = n e w V a l u e ; } ) ;
  42. S c o p e { $ $ w a

    t c h e r s : [ { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { d o c u m e n t . q u e r y S e l e c t o r ( ' i n p u t ' ) . v a l u e = n e w V a l u e ; } , g e t : f u n c t i o n ( ) { r e t u r n $ s c o p e . t i t l e ; } , l a s t : ' ' } , { e q : f a l s e , e x p : f u n c t i o n ( ) { } , f n : f u n c t i o n ( n e w V a l u e , o l d V a l u e ) { d o c u m e n t . q u e r y S e l e c t o r ( ' s p a n ' ) . i n n e r H T M L = n e w V a l u e ; } , g e t : f u n c t i o n ( ) { r e t u r n $ s c o p e . t i t l e ; } , l a s t : ' ' } ] }
  43. $digest cycle commences $scope.$apply is executed $scope.title is updated with

    input.value Angular app User types inside <input>
  44. Continues to next $$watcher until “clean ” If di erent,

    execute the “fn() ” property Re-runs $digest to ensure all $scopes are synced Compares the value to the “last ” property $digest loop Runs the “get() ” function to retrieve latest value
  45. PERFORMANCE TUNING

  46. PAIN POINT INTERPOLATION

  47. Angular evaluates entire text content Potential DOM flicker (UX) INTERPOLATION

  48. SOLUTION: CONSIDER NG-BIND < ! - - b e f

    o r e - - > < p > H e l l o { { n a m e } } a n d w e l c o m e t o F a c e b o o k ! < / p > < ! - - a f t e r - - > < p > H e l l o < s p a n n g - b i n d = " n a m e " > < / s p a n > a n d w e l c o m e t o F a c e b o o k ! < / p >
  49. PAIN POINT NG-MODEL $DIGEST FREQUENCY

  50. Change/input/etc events firing $digest per keystroke NG-MODEL $DIGEST FREQUENCY

  51. SOLUTION: NGMODELOPTIONS < i n p u t t y

    p e = " t e x t " n g - m o d e l = " v m . m o d e l " n g - m o d e l - o p t i o n s = " { u p d a t e O n : ' d e f a u l t b l u r ' , d e b o u n c e : { ' d e f a u l t ' : 2 5 0 , ' b l u r ' : 0 } } " >
  52. PAIN POINT SLOW NG-REPEAT

  53. Stalls our application thread Bad end user experience Unresponsive/crashing SLOW

    NG-REPEAT
  54. SOLUTION: ONE-TIME BINDINGS < u l > < l i

    n g - r e p e a t = " i t e m i n : : i t e m s " > { { i t e m } } < / l i > < / u l > < u l > < l i n g - r e p e a t = " i t e m i n i t e m s " > { { : : i t e m } } < / l i > < / u l >
  55. PAIN POINT EXCESSIVE DOM RE-RENDERING

  56. DOM rendering is expensive Huge DOM rendering is even more

    expensive We don't always need to re-render EXCESSIVE DOM RE-RENDERING
  57. SOLUTION: TRACK BY < u l > < l i

    n g - r e p e a t = " i t e m i n i t e m s t r a c k b y i t e m . i d " > { { i t e m } } < / l i > < / u l >
  58. PAIN POINT SLOW DOM FILTER PIPES

  59. Filters run twice per $digest Huge collections equals slow filtering

    SLOW DOM FILTER PIPES
  60. SOLUTION: CONTROLLER FILTERING f u n c t i o

    n M a i n C o n t r o l l e r ( $ f i l t e r ) { v a r c o l l e c t i o n = [ { . . . } ] ; t h i s . f i l t e r e d = c o l l e c t i o n ; t h i s . o n C l i c k = f u n c t i o n ( p r o p ) { / / D O M e q u i v a l e n t : c o l l e c t i o n | m y F i l t e r : p r o p t h i s . f i l t e r e d = $ f i l t e r ( ' m y F i l t e r ' ) ( c o l l e c t i o n , p r o p ) ; } } a n g u l a r . m o d u l e ( ' a p p ' ) . c o n t r o l l e r ( ' M a i n C o n t r o l l e r ' , M a i n C o n t r o l l e r ) ;
  61. PAIN POINT HTTP $DIGEST BATCHING

  62. Multiple XHR's will each fire $digest HTTP $DIGEST BATCHING

  63. SOLUTION: $HTTP + $APPLYASYNC f u n c t i

    o n c o n f i g ( $ h t t p P r o v i d e r ) { $ h t t p P r o v i d e r . u s e A p p l y A s y n c ( t r u e ) ; } a n g u l a r . m o d u l e ( ' a p p ' , [ ] ) . c o n f i g ( c o n f i g ) ;
  64. PAIN POINT INTERNAL DI COMPILE SPEEDS

  65. We expect too much from Angular INTERNAL DI COMPILE SPEEDS

  66. SOLUTION: STRICT DI MODE / / u s a g

    e : < h t m l n g - s t r i c t - d i > f u n c t i o n S o m e S e r v i c e ( $ s c o p e , $ t i m e o u t ) { / / . . . } / / A r r a y a n n o t a t i o n s S o m e S e r v i c e . $ i n j e c t = [ ' $ s c o p e ' , ' $ t i m e o u t ' ] ; a n g u l a r . m o d u l e ( ' a p p ' ) / / I n l i n e a n n o t a t i o n s . f a c t o r y ( ' S o m e S e r v i c e ' , [ ' $ s c o p e ' , ' $ t i m e o u t ' , S o m e S e r v i c e ] ) ;
  67. PAIN POINT NEEDLESS $$WATCHERS FROM DIRECTIVES

  68. Choosing ng-if/ng-switch Choosing ng-show/ng-hide NEEDLESS $$WATCHERS FROM DIRECTIVES

  69. SOLUTION: UNDERSTANDING < ! - - n g - i

    f / n g - s w i t c h - - > < u l n g - i f = " v m . e x p o s e N a v " > < l i n g - r e p e a t = " m e n u i n v m . m e n u s " > < / l i > < / u l > < ! - - n g - s h o w / n g - h i d e - - > < u l n g - s h o w = " v m . e x p o s e N a v " > < l i n g - r e p e a t = " m e n u i n v m . m e n u s " > < / l i > < / u l >
  70. PAIN POINT EXTRA DOM QUERYING/PROCESSING

  71. Internal .data() calls for binding info Class name additions EXTRA

    DOM QUERYING/PROCESSING
  72. SOLUTION: DISABLE DEBUG INFO f u n c t i

    o n c o n f i g ( $ c o m p i l e P r o v i d e r ) { $ c o m p i l e P r o v i d e r . d e b u g I n f o E n a b l e d ( f a l s e ) ; } a n g u l a r . m o d u l e ( ' a p p ' , [ ] ) . c o n f i g ( c o n f i g ) ;
  73. SOLUTION: DISABLE DEBUG INFO < ! - - e n

    a b l e d - - > < d i v n g - c o n t r o l l e r = " M a i n C t r l a s v m " c l a s s = " n g - s c o p e n g - b i n d i n g " > < m y - d i r e c t i v e c l a s s = " n g - i s o l a t e - s c o p e " > < / m y - d i r e c t i v e > < / d i v > < ! - - d i s a b l e d - - > < d i v n g - c o n t r o l l e r = " M a i n C t r l a s v m " > < m y - d i r e c t i v e > < / m y - d i r e c t i v e > < / d i v >
  74. THAT'S ALL FOLKS! UNTIL NEXT TIME :)