class: center, middle, cover # perf.html ## a profiler for Firefox --- # Me .float-left[  ] .float-left[ * [Julien Wajsberg](https://twitter.com/jwajsberg) * from Paris * at Mozilla for 5 years * developer on [perf.html](https://github.com/devtools-html/perf.html/) for 1 year ] --- # What's the plan? 1. A sampling profiler 2. Call trees 3. The timeline 4. Markers 5. Analyzing a profile --- # A _sampling_ profiler * every millisecond we stop Firefox and look at the stack on every thread * when we capture we gather all these measurements in one profile * then we _merge_ the stacks into a _call tree_ --- # An example, maybe? ```javascript function a() { b(); } function b() { c(); } function c() { doWork(); } function doWork() { for (let i = 0; i < 1e7; i += Math.random()) {} } a(); ``` --- # Taking a sample every 1ms: ``` 1ms 2ms 3ms 4ms 5ms 6ms ----- ----- ----- ----- ----- ----- a a a a a a ↓ ↓ ↓ ↓ ↓ ↓ b b b b b b ↓ ↓ ↓ ↓ ↓ ↓ c c c c c c ↓ ↓ ↓ ↓ ↓ ↓ doWork doWork doWork doWork doWork doWork ``` --- # A simple call tree ``` a (Running time: 6ms) (Self time: 0ms) ↓ b (Running time: 6ms) (Self time: 0ms) ↓ c (Running time: 6ms) (Self time: 0ms) ↓ doWork (Running time: 6ms) (Self time: 6ms) ``` --- # In the profiler  .center[[Build a simple call tree, for real](examples/a-simple-call-tree.html)] --- # Another example ```javascript function a() { b(); } function b() { c(); } function c() { for (let i = 0; i < 1e7; i += Math.random()) { doNothing(); } } function doNothing() { } a(); ``` --- # A simpler call tree ! ``` a (Running time: 6ms) (Self time: 0ms) ↓ b (Running time: 6ms) (Self time: 0ms) ↓ c (Running time: 6ms) (Self time: 6ms) ``` ??? We spend too less time in doNothing, so it never shows up when we stop Firefox to get a sample. We might get one by chance sometimes. --- # Slightly different .smaller[ ```javascript function a() { b(); } function b() { c(); } function c() { for (let i = 0; i < 1e7; i += Math.random()) { doWork(); } } function doWork() { for (let i = 0; i < 100; i += Math.random()) { } } a(); ``` ] --- # Same call tree as the first example ``` a (Running time: 6ms) (Self time: 0ms) ↓ b (Running time: 6ms) (Self time: 0ms) ↓ c (Running time: 6ms) (Self time: 0ms) ↓ doWork (Running time: 6ms) (Self time: 6ms) ``` ??? This time we spend enough time in doWork. What's important to see is that even if we call doWork several times we see it only once in the call tree. --- # A more complex code .smallest[ ```javascript function a() { b(); } function b() { c(); h(); } function c() { d(); f(); } function d() { e(); } function e() { for (let i = 0; i < 1e7; i += Math.random()) {} } function f() { * for (let i = 0; i < 1e7; i += Math.random()) {} g(); } function g() { for (let i = 0; i < 1e7; i += Math.random()) {} } function h() { f(); } a(); ``` ] --- # More samples! .center[  ] ??? Every ms we get a new stack. --- # A call tree with branches! .center[  [Do it yourself!](examples/a-branched-call-tree.html) ] ??? We merge the functions into a call tree with branches. --- # In perf.html .center[  ] ??? See especially the running times: we clearly see we spend time in `f`. --- # Call tree inversion .center[  ] ??? Inverting the call tree makes it easier to see the functions where we spend the most time. --- # The timeline .center[  ] * This actually shows the stack. * Changes in the height mean _changes in the stack_. * This is _not_ the CPU usage. --- # Markers * Because we control Gecko's source code, we can _instrument_ it at all the right places * Just like developers can _instrument_ their own code with `performance.mark`. .center[  ] --- # Markers and call trees * markers are supplementary to the call tree * we'll always get all markers * markers for important events: reflows, garbage collection, DOMEvent * we generate special markers for when the event loop is stuck --- # How do _you_ use it? .smaller[ ## Solution 1 1. Go to https://perf-html.io 2. Install the addon 3. Record from the added icon. ## Solution 2 1. Enable the new performance recorder in the Developer Tools' settings 2. Open the _Performance_ panel in the developer tools. 3. Record from the panel. ] --- # Some more analyses * [DOM mutations](examples/dom-mutation.html) * [Garbage collection](examples/merge-sort.html) --- # Thank you ! _INSERT FUNNY ANIMATED GIF HERE_ You can always find this presentation [online on github](https://github.com/julienw/fosdem-2018-perf-html-talk/) and even [watch it online](https://julienw.github.io/fosdem-2018-perf-html-talk/). Thanks to my wonderful coworkers [Greg Tatum](https://twitter.com/TatumCreative/) and [Markus Stange](https://twitter.com/markusstange). _QUESTIONS?_