Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Browser Internals for JS Devs: WebU Toronto 2016 by Alex Blom


Published on

Talk on Browser Internals for JS Devs by Alex Blom of Isle of Code & ember-cordova at WebU 2016 Toronto.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Browser Internals for JS Devs: WebU Toronto 2016 by Alex Blom

  1. 1. Browser Internals for JS Devs @alexblom
  2. 2. Isle of Code • Toronto based development; • Focused on Ember, Cordova & Electron;
  3. 3. ember-cordova • • Managed / run by Isle of Code; • Makes packaging hybrid apps for ember really easy; • When you work on hybrid, render performance & memory management are things you have to deal with;
  4. 4. A Browsers Job • Get and present the selected resource; • For the purpose of this talk, we are assuming HTML;
  5. 5. JS / Render Engines • Chrome uses V8 / Blink; • Safari uses Nitro / Webkit / Webcore;
  6. 6.
  7. 7. Threads • There are two threads: • Main: Running JS, CSS Styles, layout & painting; • Compositor: Drawing bitmaps via GPU, visibility, scroll;
  8. 8.
  9. 9. DOM Tree • The DOM Tree has one tag per item, but does not really hold content; • e.g. • document • head • title • body • p • text node • In WebKit, the root node is Node.h • Note that there are documents, elements & text;
  10. 10. Render Tree • The Render tree is the visual part of the DOM • e.g. • root • body • div • line 1 • line 2 • The root is the element that contains all other elems • May contains elms that do not have any DOM information
  11. 11. WebCore Representations • RenderFlow.h; • RenderBlock.h; • RenderInline.h;
  12. 12. Parsing HTML is Hard • It allows invalid tags and keeps going, e.g. • Missing closing tags; • Putting content outside of body; • Closing tags too early; • Unlike most parsers, it works hard on your behalf & protects you;
  13. 13. Execution stops at Script Tags • This is why including scripts at the end of <body> is important; • In HTML5, you can include an async tag: • <script src=“ember.js” async></script>
  14. 14. Layout • Layout information is often cached, so on e.g. resize events, the sizes are taken from a cache; • Layout often involves: 1 Parent renderer determines its own width. 2 Parent goes over children and: 1 Place the child renderer (sets its x and y). 2 Calls child layout if needed–they are dirty or we are in a global layout, or for some other reason–which calculates the child's height. 3 Parent uses children's accumulative heights and the heights of margins and padding to set its own height–this will be used by the parent renderer's parent. 4 Sets its dirty bit to false.
  15. 15. Paint Order 1. Background colour; 2. Background image; 3. Border; 4. Children; 5. Outline;
  16. 16. Tokenization Example • <i> webu <i> would yield: • start-tag: i; • char-tag: w/e/b/u • end-tag: i;
  17. 17. for vs while
  18. 18. setTimeout is best effort
  19. 19. Manage Reflows
  20. 20. What causes Reflow? • Resizing the browser window; • using JavaScript methods involving computed styles; • adding or removing elements from the DOM; and • changing an element's classes. • w
  21. 21. visibility:hidden CSS transforms only affect the selected element, not those around it
  22. 22.
  23. 23.
  24. 24. Examples
  25. 25. Best Practices for avoiding Reflow 1. Avoid setting multiple inline styles; avoid setting styles individually. 2. Use class names of elements, and do so as low in the DOM tree as possible. 3. Batch your DOM changes and perform them offline; 4. Avoid computing styles too often. If you must then cache those values. 5. Apply animations with position: fixed or absolute so it doesn’t affect the layout of other elements. 6. Avoid table layouts, they trigger more reflows than block layouts because multiple passes must be made over the elements. 7. Reduce unnecessary DOM depth. Changes at one level in the DOM tree can cause changes at every level of the tree - all the way up to the root, and all the the way down into the children of the modified node. This leads to more time being spent performing reflow. 8. Minimize CSS rules and remove unused CSS rules. 9. If you make complex rendering changes such as animations, do so out of the flow. Use position-absolute or position-fixed to accomplish this. 10.Avoid unnecessary complex CSS selectors - descendant selectors in particular.
  26. 26. Coalesce Changes or Work on a local fragment
  27. 27. Animation Frames • ~15ms target; • Taking longer will clog your thread; • This 15ms target includes the work your browser needs to do. Best to target ~10; • Allows the browser to batch animation work;
  28. 28. Example
  29. 29. Measuring Performance
  30. 30. Profiling • CPU Profiler: What is taking longest to run?; • Timeline: Rendering performance & bottlenecks; • Timers: Measure events; • Heap Profile: Memory, detached nodes; • Visual: Subjective;
  31. 31. Examples
  32. 32. Memory Leaks • Garbage Collection: 2 types: • Young Generation & Old Generation
  33. 33.
  34. 34. Name closures for better profiling
  35. 35.
  36. 36. v new Date()
  37. 37. node / command line • Built in as of Node 4.4; • add —prof tag • node —prof foo.js • node —prof-process isolate-* > foo.txt
  38. 38. Using too much memory has negative implications
  39. 39. http://www- 2005.pdf
  40. 40. V8 • V8 compiles JS to native code before executing There are no steps for interpretation or bytecode; • Compilation usually won’t happen until a function is called; • Compilation happens one function at a time;
  42. 42. Compilers • General compiler & optimization compiler (TurboFan); • Code runs through general compiler first; • V8 identifies hot code for optimization; • Code via optimization compiler runs up to 100x faster; • Applies to the containing function - not blocks;
  43. 43. Not Optimizable • Generator functions; • debugger; • eval; • with; • __proto__; • rest params; • compound let/const; • try/catch & try/finally;
  44. 44. Leaking or re-assigning arguments
  45. 45. Leaking or re-assigning arguments
  46. 46. Leaking or re-assigning arguments
  47. 47. • In non-strict, V8 preserves the bindings between arguments[0] & arg0. If you re-assign, V8 says ‘too hard’ and bails out (choses to not optimize); • It expects arg0 & arguments[0] to have the same hidden class; • Using strict does not preserve bindings, meaning the code can be optimized; Leaking or re-assigning arguments
  48. 48. Safe arguments • arguments[n], where n is defined and not a param; • apply(arguments); • arguments.length;
  49. 49. Not Optimizable • Generator functions; • debugger; • eval; • with; • __proto__; • rest params; • compound let/const; • try/catch & try/finally;
  50. 50. Isolate non optimizable code into small functions
  51. 51. Hidden Classes • Keeping track of dynamic, changing classes is hard; • V8 assigns hidden to represent objects;
  52. 52. • The first hidden class is initialized on the ‘new’ invocation (C0); C0
  53. 53. • The first hidden class is initialized on the ‘new’ invocation (C0); • The second is initialized when language is assigned (C1); C0 C1
  54. 54. • The first hidden class is initialized on the ‘new’ invocation (C0); • The second is initialized when language is assigned (C1); • The third is initialized when skill is assigned (C2); • goodProgrammer has a class of C2; C0 C1 C2
  55. 55. Class Chain • C0 is a hidden class that is an empty object; • C1 is based on C0, with a language property; • C2 is based on C1, with a skill property; • C0 -> C1 -> C2;
  56. 56. • Same hidden classes can be used. Both programmers have a hidden class of C2; C0 C1 C2 C0
  57. 57. Hidden Class can no longer be re-used • C0 -> C1 -> C2 can no longer be used for badProgrammer. The shape of the objects are different; • A new hidden class is created for the extra property, which is only attached to badProgrammer; • Now V8 is tracking two classes, and is unlikely to optimize;
  58. 58. Order matters • Assigning properties in different orders results in different hidden classes; • Consider hidden classes to be a linked list, where the class is the last node (they are not);
  59. 59. Consistently having this problem is not really a JS problem. You have a modelling problem.
  60. 60. Monomorphic vs Polymorphic • Monomorphic are hidden classes that are always passed the same object type (e.g. String); • V8 assumes classes are monomorphic. Passing a different object type to the same function requires a new hidden class to be created;
  61. 61. Optimize Mobile • Payload <500kb, 1mb is often safe; • <5k nodes, <10k in extreme circumstances; • Coalesce network requests;
  62. 62. Further Reading • imization-killers • /howbrowserswork/
  63. 63. Browser Internals for JS Devs @alexblom