Bug 1752374 - [devtools documentation] Remove the documentation about the old performance panel r=jdescottes DONTBUILD

This replaces the documentation by a link to the online documentation to
the Firefox Profiler.

Differential Revision: https://phabricator.services.mozilla.com/D150005
This commit is contained in:
Julien Wajsberg 2022-06-23 12:20:01 +00:00
Родитель 1dc49750b8
Коммит bee5e18654
88 изменённых файлов: 7 добавлений и 1600 удалений

Просмотреть файл

@ -105,13 +105,13 @@ Network Monitor
See the network requests made when a page is loaded.
Performance Tools
Performance Panel
-----------------
.. image:: landingpage_performance.png
.. image:: landingpage_performance_2022.png
:class: border
:target: performance
:alt: Performance Tools in Firefox 57 Developer Tools.
:target: https://profiler.firefox.com/docs/
:alt: Performance Panel in Firefox 103 Developer Tools.
Analyze your site's general responsiveness, JavaScript, and layout performance.

Двоичные данные
devtools/docs/user/landingpage_performance.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичные данные
devtools/docs/user/landingpage_performance_2022.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 24 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 61 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 55 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 27 KiB

Просмотреть файл

@ -1,89 +0,0 @@
===========
Allocations
===========
The Allocations view in the Performance tool shows you which functions in your page are allocating the most memory over the course of the profile.
For performance this is important mostly because allocating a lot of memory, or making a lot of allocations, can trigger :ref:`garbage collection <performance-allocations-and-garbage-collection>`. This in turn can hurt the responsiveness of a page.
The Allocations view is new in Firefox 46.
To enable the Allocations view, you must check "Record Allocations" in the Performance tool settings, *before* recording a profile. Then :ref:`record a profile <performance-how-to-record-a-profile>` as usual, and you will see a new tab labeled "Allocations" in the toolbar:
.. raw:: html
<iframe width="560" height="315" src="https://www.youtube.com/embed/WBmttwfA_k8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<br/>
<br/>
Anatomy of the allocations view
*******************************
The allocations view looks something like this:
.. image:: allocations-view-1.png
:class: border
The allocations view periodically samples allocations that are made over the recording. Each row represents a function in which at least one allocation-sample was taken during the recording.
It includes the following columns:
- Self Count: the number of allocation-samples that were taken in this function (also shown as a percentage of the total)
- Self Bytes: the total number of bytes allocated in the allocation-samples in this function (also shown as a percentage of the total)
Rows are sorted by the "Self Bytes" column.
So in the example above:
- 8904 samples were taken in ``signalLater()``, which is 28.57% of the total number of samples taken
- those samples allocated 1102888 bytes, which is 30.01% of the total memory allocated in all samples
Next to each function name is a disclosure arrow. Click this to see the places this function was called from:
.. image:: allocations-view-2.png
:class: center
Here you can see that ``signalLater()`` was called from two places: ``removeInner()`` and ``setSelectionInner()``. In this way you can walk back up the call stack, and understand better the context for these allocations.
Self Cost and Total Cost
------------------------
You'll see that there are separate sets of columns for "Self" and for "Total". "Self" records samples taken only in this function. "Total" records samples taken in this function or in functions called by this function. At the top level, these are always the same, since the view presents "leaf" functions at the top level (that is, it presents an inverted view of the call stack). But if you start walking back up the call stack, you'll see the difference:
.. image:: allocations-view-2.png
:class: center
Here, 8904 samples were taken in ``signalLater()``. But ``signalLater()`` was called from two places: ``removeInner()`` and ``setSelectionInner()``. Both these functions have 0 in Self Count, meaning that no allocations were seen directly in these functions. However, ``removeInner()`` has 8901 in Total Count, while``setSelectionInner()`` has just 3 in Total Count. This is telling us that, of the 8904 allocations seen in ``signalLater()``, all but three came through the ``removeInner()`` branch.
.. _performance-allocations-and-garbage-collection:
Allocations and garbage collection
**********************************
Of course, the memory allocated by a site is in itself useful information to know. But the main connection between the allocation profile of a site and its responsiveness is the cost of garbage collection (GC).
With a garbage-collected language, like JavaScript, the runtime periodically needs to walk the heap looking for objects that are no longer :ref:`reachable <memory-dominators-reachability>`, and then freeing the memory they occupy. While GC events like this are executing, the JavaScript engine must be paused, so your program is suspended and will be completely unresponsive.
To reduce the impact on responsiveness, `SpiderMonkey <https://spidermonkey.dev/>`_ (the JavaScript engine in Firefox) can perform GC in small increments, letting the program run in between. Sometimes, though, it needs to perform a full non-incremental collection, and the program has to wait for it to finish.
GC events are shown as red markers in the :doc:`Waterfall <../waterfall/index>` view, and are a big red flag for responsiveness, sometimes running for hundreds of milliseconds:
.. image:: allocations-view-long-gc.png
:class: center
If you're seeing GC events in your site's performance profile, what can you do? SpiderMonkey uses a `complex set of heuristics <https://dxr.mozilla.org/mozilla-central/rev/584870f1cbc5d060a57e147ce249f736956e2b62/js/src/gc/GCRuntime.h#192>`_ to decide when to do what sort of garbage collection.
In general, though: *allocation pressure - allocating a lot of memory, or allocating memory at a high rate - makes SpiderMonkey more likely to run garbage collection, and more likely to run full, non-incremental garbage collection.*
If a GC event was caused by allocation pressure, then the sidebar on the right of the marker in the Waterfall view contains a link labeled "Show allocation triggers". If you click this link, the devtools switches to the allocations view, and selects the region of time from the end of the last GC cycle to the start of the one you clicked on. This shows you all the allocations that collectively triggered this GC event.
If you're seeing these problems, consider whether you can reduce the number or size of the allocations you're making here. For example:
- can you allocate memory lazily, when it is actually needed, instead of up front?
- if allocating memory in a loop, can you reuse a single allocation in every loop iteration?

Просмотреть файл

@ -1,130 +0,0 @@
=========
Call Tree
=========
The Call Tree tells you which JavaScript functions the browser spent the most time in. By analyzing its results, you can find bottlenecks in your code - places where the browser is spending a disproportionately large amount of time.
These bottlenecks are the places where any optimizations you can make will have the biggest impact.
The Call Tree is a sampling profiler. It periodically samples the state of the JavaScript engine and records the stack for the code executing at the time. Statistically, the number of samples taken in which we were executing a particular function corresponds to the amount of time the browser spent executing it.
.. note::
In this article, we'll use the output of a simple program as an example. If you want to get the program to experiment with your profile, you can find it `here <https://github.com/mdn/performance-scenarios/blob/gh-pages/js-call-tree-1/>`__. You can find the specific profile we discuss `here <https://github.com/mdn/performance-scenarios/blob/gh-pages/js-call-tree-1/profile/call-tree.json>`__ - just import it to the performance tool to follow along.
There's a short page describing the structure of this program :doc:`here <../examples/sorting_algorithms_comparison/index>`.
Note that we use the same program - the same profile, in fact - in the documentation page for the :doc:`Flame Chart <../flame_chart/index>`.
The screenshot below shows the output of a program that compares three sorting algorithms - bubble sort, selection sort, and quicksort. To do this, it generates some arrays filled with random integers and sorts them using each algorithm in turn.
We've :ref:`zoomed <performance-ui-tour-zooming-in>` into the part of the recording that shows a long JavaScript marker:
.. image:: perf-call-tree.png
:class: center
The Call Tree presents the results in a table. Each row represents a function in which at least one sample was taken, and the rows are ordered by the number of samples taken while in that function, highest to lowest.
- *Samples* is the number of samples that were taken when we were executing this particular function, including its children (the other functions called by this particular function).
- *Total Time* is that number translated into milliseconds, based on the total amount of time covered by the selected portion of the recording. These numbers should roughly be the same as the number of samples.
- *Total Cost* is that number as a percentage of the total number of samples in the selected portion of the recording.
- *Self Time* is calculated as the time spent in that particular function, excluding its children. This comes from the captured stacks where this function is the leafmost function.
- *Self Cost* is calculated from *Self Time* as a percentage of the total number of samples in the selected portion of the recording.
In the current version of the Call Tree, these are the most important columns. Functions with a relatively high *Self Cost* are good candidates for optimization, either because they take a long time to run, or because they are called very often.
.. note::
:ref:`The inverted call tree <performance-call-tree-using_an_inverted_aka_bottom-up_call_tree>` is a good way to focus on these *Self Cost* values.
This screenshot tells us something we probably already knew: Bubble sort is a very inefficient algorithm. We have about six times as many samples in bubble sort as in selection sort, and 13 times as many as in quicksort.
Walking up the call tree
************************
Next to each function name is a disclosure arrow: Click that, and you can see the path back up the call tree, from the function in which the sample was taken, to the root. For example, we can expand the entry for ``bubbleSort()``:
.. image:: perf-call-tree-expanded-bubblesort.png
:class: center
So we can see the call graph is like this:
.. code-block:: JavaScript
sortAll()
-> sort()
-> bubbleSort()
Note also that *Self Cost* for ``sort()`` here is 1.45%, and note that this is the same as for the separate entry for ``sort()`` later in the list. This is telling us that some samples were taken in ``sort()`` itself, rather than in the functions it calls.
Sometimes there's more than one path back from an entry to the top level. Let's expand the entry for ``swap()``:
.. image:: perf-call-tree-expanded-sawp.png
:class: center
There were 253 samples taken inside ``swap()``. But ``swap()`` was reached by two different paths: both ``bubbleSort()`` and ``selectionSort()`` use it. We can also see that 252 of the 253 samples in ``swap() ``were taken in the ``bubbleSort()`` branch, and only one in the ``selectionSort()`` branch.
This result means that bubble sort is even less efficient than we had thought! It can shoulder the blame for another 252 samples, or almost another 10% of the total cost.
With this kind of digging, we can figure out the whole call graph, with associated sample count:
.. code-block:: JavaScript
sortAll() // 8
-> sort() // 37
-> bubbleSort() // 1345
-> swap() // 252
-> selectionSort() // 190
-> swap() // 1
-> quickSort() // 103
-> partition() // 12
Platform data
*************
You'll also see some rows labeled *Gecko*, *Input &amp; Events*, and so on. These represent internal browser calls.
This can be useful information too. If your site is making the browser work hard, this might not show up as samples recorded in your code, but it is still your problem.
In our example, there are 679 samples assigned to *Gecko* - the second-largest group after ``bubbleSort()``. Let's expand that:
.. image:: perf-call-tree-expanded-gecko.png
:class: center
This result is telling us that 614 of those samples, or about 20% of the total cost, are coming from our ``sort()`` call. If we look at the code for ``sort()``, it should be fairly obvious that the high platform data cost is coming from repeated calls to ``console.log()``:
.. code-block:: JavaScript
function sort(unsorted) {
console.log(bubbleSort(unsorted));
console.log(selectionSort(unsorted));
console.log(quickSort(unsorted));
}
It would certainly be worthwhile considering more efficient ways of implementing this.
One thing to be aware of here is that idle time is classified as *Gecko*, so parts of your profile where your JavaScript isn't running will contribute *Gecko* samples. These aren't relevant to the performance of your site.
.. note::
By default, the Call Tree doesn't split platform data out into separate functions, because they add a great deal of noise, and the details are not likely to be useful to people not working on Firefox. If you want to see the details, check "Show Gecko Platform Data" in the :ref:`Settings <performance-ui-tour-toolbar>`.
.. _performance-call-tree-using_an_inverted_aka_bottom-up_call_tree:
Using an inverted, aka Bottom-Up, Call Tree
*******************************************
An inverted call tree reverses the order of all stacks, putting the leafmost function calls at the top. The direct consequence is that this is a view that focuses more on the function's *Self Time* information. This is a very useful view to find some hot spot in your code.
To display this view, click the gear icon on the right-hand end of the performance tab and select **Invert Call Tree**.
.. image:: performance_menu_invert_call_tree.png
:class: center

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 50 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 46 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 63 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 46 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.4 KiB

Просмотреть файл

@ -1,7 +0,0 @@
========
Examples
========
List of demo pages for performance scenarios and walkthroughs.
- :doc:`Sorting algorithms comparison <sorting_algorithms_comparison/index>`

Просмотреть файл

@ -1,60 +0,0 @@
=============================
Sorting algorithms comparison
=============================
This article describes a simple example program that we use in two of the Performance guides: the guide to the :doc:`Call Tree <../../call_tree/index>` and the guide to the :doc:`Flame Chart <../../flame_chart/index>`.
This program compares the performance of three different sorting algorithms:
- bubble sort
- selection sort
- quicksort
It consists of the following functions:
.. list-table::
:widths: 30 70
:header-rows: 0
* - :doc:`about:debugging <about_colon_debugging/index>`
- Debug add-ons, content tabs, and workers running in the browser.
* - **sortAll()**
- Top-level function. Iteratively (200 iterations) generates a randomized array and calls ``sort()``.
* - **sort()**
- Calls each of ``bubbleSort()``, ``selectionSort()``, ``quickSort()`` in turn and logs the result.
* - **bubbleSort()**
- Implements a bubble sort, returning the sorted array.
* - **selectionSort()**
- Implements a selection sort, returning the sorted array.
* - **quickSort()**
- Implements quicksort, returning the sorted array.
* - **swap()**
- Helper function for ``bubbleSort()`` and ``selectionSort()``.
* - **partition()**
- Helper function for ``quickSort()``.
Its call graph looks like this:
.. code-block:: JavaScript
sortAll() // (generate random array, then call sort) x 200
-> sort() // sort with each algorithm, log the result
-> bubbleSort()
-> swap()
-> selectionSort()
-> swap()
-> quickSort()
-> partition()
The implementations of the sorting algorithms in the program are taken from https://github.com/nzakas/computer-science-in-javascript/ and are used under the MIT license.
You can try out the example program `here <https://mdn.github.io/performance-scenarios/js-call-tree-1/index.html>`__ and clone the code `here <https://github.com/mdn/performance-scenarios>`__ (be sure to check out the gh-pages branch). You can also `download the specific profile we discuss <https://github.com/mdn/performance-scenarios/tree/gh-pages/js-call-tree-1/profile>`__ - just import it to the Performance tool if you want to follow along. Of course, you can generate your own profile, too, but the numbers will be a little different.

Просмотреть файл

@ -1,100 +0,0 @@
===========
Flame Chart
===========
The Flame Chart shows you the state of the JavaScript stack for your code at every millisecond during the performance profile.
This gives you a way to know exactly which function was executing at any point during the recording, how long it ran for, and where it was called from.
The Call Tree and the Flame Chart are both used to analyze your site's JavaScript, and they both use the same data: a sample of the JavaScript engine's stack, taken periodically during the recording.
But while the Call Tree organizes this data to show you where your program is spending most time in aggregate across the recording, the Flame Chart uses it to show you when in the recording particular functions are executing. Essentially it shows you the state of the call stack at any given point during the recording.
Here's a screenshot showing the Flame Chart for a section of a profile:
.. image:: perf-flame-chart-overview.png
:class: center
First of all, you'll see that, in the :ref:`recording overview pane <performance-ui-tour-recording-overview>`, we've selected a small slice of the recording to view in the Flame Chart. The Flame Chart displays a lot of data, so to get readable results, it's usually necessary to zoom in.
In the Flame Chart view itself, along the X-axis is time. The screenshot above covers the period from 1435ms to a little past 1465ms. Along the Y-axis are the functions on the call stack at that point in time, with the top-level at the top, and the leaf function at the bottom. Functions are color-coded to make them easier to distinguish.
This gives you a way to know exactly which function was executing at any point during the recording, how long it ran for, and where it was called from.
Zooming and panning
*******************
To work effectively with the Flame Chart, you'll need to be able to navigate it. There are two main controls you can use to navigate the Flame Chart:
.. list-table::
:widths: 50 50
:header-rows: 0
* - **Zoom**: increase/decrease the selected portion of the complete profile that's displayed in the Flame Chart
- 1) Mouse wheel up/down in the Flame Chart.
2) Trackpad 2 fingers up/down in the Flame Chart.
* - **Pan**: move the selected portion of the complete profile left and right
- 1) Click and drag the selected portion in the :ref:`recording overview pane <performance-ui-tour-recording-overview>`.
2) Click and drag anywhere in the Flame Chart.
An example
**********
To see how the Flame Chart can reveal the behavior of your program, we'll look at a simple example. We'll use the same example as in the :doc:`Call Tree <../call_tree/index>` page: a program that compares three different sorting algorithms. There's a :doc:`separate page <../examples/sorting_algorithms_comparison/index>` that gives an overview of this program's structure.
We'll use the same profile file as that used in the Call Tree page. In the call tree page, we figured out that the program call graph in that profile, and the associated sample count, looked like this:
.. code-block:: JavaScript
sortAll() // 8
-> sort() // 37
-> bubbleSort() // 1345
-> swap() // 252
-> selectionSort() // 190
-> swap() // 1
-> quickSort() // 103
-> partition() // 12
First, we'll just select the whole section in which the program was active:
.. image:: perf-flame-chart-zoomed-out.png
:class: center
At the top, colored purple, is the ``sortAll()`` call, running throughout the program from start to finish. Underneath that, colored olive-green, are the calls it's making to ``sort()``. Underneath that, like the teeth of a comb, are all the calls being made to each sorting algorithm.
Let's zoom in:
.. image:: perf-flame-chart-zoom-1.png
:class: center
This slice is about 140 ms long, and shows us more details of the functions being called by ``sort()``. The ``sort()`` code is just this:
.. code-block:: JavaScript
function sort(unsorted) {
console.log(bubbleSort(unsorted));
console.log(selectionSort(unsorted));
console.log(quickSort(unsorted));
}
The markers labeled "bubb..." and colored olive-green are presumably ``bubbleSort()``. The ones colored plain green are presumably the other sort functions. Even at a glance, we can see that the bubble sort blocks are much wider (of a longer duration) than the others.
We can also see some functions being called from ``bubbleSort()``, colored purple.
Let's zoom in one more time:
.. image:: perf-flame-chart-zoom-2.png
:class: center
This slice is about 20ms long. We can see that the purple markers underneath ``bubbleSort()`` are the calls to ``swap()``. If you counted them all, the Call Tree view tells us that you'd see 253 of them. All the ones in this zoom are underneath ``bubbleSort()``, but according to the Call Tree view, the profile does contain one under ``selectionSort()``.
We can also see that two of the green markers are for ``selectionSort()`` and ``quickSort()``, but we're also seeing calls to platform (Gecko) code in between our calls to the sorting functions. It seems very likely that this is from the ``console.log()`` calls in ``sort()``.

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 65 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 15 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 16 KiB

Просмотреть файл

@ -1,65 +0,0 @@
==========
Frame rate
==========
Frame rate is a measure of awebsite's responsiveness. A low or inconsistent frame rate can make a site appear unresponsive or janky, making for a bad user experience.
**A frame rate of 60fps is the target for smooth performance, giving you a time budget of 16.7ms for all the updates needed in response to some event.**
The frame rate graph in the Performance tool shows you the frame rate over the course of a recording. It gives you a quick indication of where your site might be having problems, enabling you to use the other tools for a more in-depth analysis.
Frame rate and responsiveness
*****************************
Frame rate is the rate at which a video device can produce images (or frames). It's most familiar from film and gaming, but is now widely used as a performance measure for websites and web apps.
In web performance, a frame encapsulates the work the browser needs to do in order to update and repaint the screen. Frame rate is most obviously applicable to animations: if the frame rate is too low, an animation will have a jerky appearance, while a faster frame rate will be smoother. But frame rate is also useful as a general measure of a site's responsiveness as the user interacts with it.
For example, if moving the mouse over some page element triggers some JavaScript that changes the element's appearance, and that triggers a reflow and a repaint, then all this work needs to be completed in that frame. If it takes too long for the browser to process the frame, then the browser will appear momentarily unresponsive (janky).
Similarly, if scrolling through a page involves a lot of complex page updates and the browser can't keep up an acceptable frame rate, scrolling the page will appear sluggish or will occasionally freeze.
In general, a high and consistent frame rate will make the user's interaction with the site more enjoyable and engaging.
.. note::
A frame rate of 60fps is reckoned to be the target for smooth performance, giving you a time budget of 16.7ms for all the updates that need to be made synchronously in response to some event.
However, consistency is especially important: if you can't deliver 60fps, it's better to deliver lower frame rates more consistently, and avoid sudden dips in the frame rate which cause the site to freeze.
Frame rate graph
****************
The frame rate graph is found in the :ref:`Recording overview <performance-ui-tour-recording-overview>` part of the Performance tool. It takes a timestamp when the browser finishes a frame, and uses this to keep track of the frame rate over the course of the recording.
.. image:: perf-frame-rate.png
:class: center
The x-axis is time over the profile period, and there are three annotations: the maximum frame rate, the average frame rate, and the lowest frame rate.
Using the frame rate graph
**************************
The great value of the frame rate graph is that, like the :doc:`Web Console <../../web_console/index>`, it gives you a quick indication of where your site might be having problems, enabling you to use the other tools for more in-depth analysis. For example, here's a screenshot of a performance profile:
.. image:: perf-fr-waterfall.png
:class: center
You can see that the average frame rate is reasonably healthy, but there are three spots where frame rate collapses for tens of milliseconds. This would certainly cause a noticeable stutter for any animations that were playing in the page.
The frame rate graph is correlated with the :ref:`waterfall summary <performance-ui-tour-waterfall-overview>` directly above it, and there we can see that the first two drops in the frame rate are correlated with orange bars, which denote time spent executing JavaScript.
If we select one of these slices of the recording, the main :doc:`Waterfall view <../waterfall/index>` underneath it is zoomed into it, and we can see the function that's causing the problem:
.. image:: perf-zoom.png
:class: center
We have a JavaScript function from a click event that's blocking the main thread for 170 milliseconds.
Which function, though? Switch to the :doc:`Flame Chart <../flame_chart/index>` to see the call stack at that point:
.. image:: perf-fr-flame-chart.png
:class: center
The offending function is called ``doPointlessComputations()``, and it's defined in "main.js". To fix it, we might consider splitting it into pieces and running the pieces inside `requestAnimationFrame <https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame>`_, or even running the entire function in a `worker <https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers>`_. The :doc:`Intensive JavaScript <../scenarios/intensive_javascript/index>` article shows how you can use strategies like this to fix responsiveness problems caused by long-running synchronous JavaScript.

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 18 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 22 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 8.0 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 23 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 13 KiB

Просмотреть файл

@ -1,85 +0,0 @@
======
How to
======
Open the Performance tools
**************************
To open the Performance tools:
- press :kbd:`Shift` + :kbd:`F5`
- select "Performance" from the Web Developer submenu in the Firefox Menu (or Tools menu if you display the menu bar or are on OSX)
- select "Performance" from Tools button, in the Toolbar, if you have one:
.. image:: devtools-button.png
:class: center
.. _performance-how-to-record-a-profile:
Record a profile
****************
To start a new recording, press the stopwatch icon in the Recordings pane. To stop, press it again:
.. image:: perf-record.png
:class: center
You can also start and stop recording from the Web Console, using `console.profile() <https://developer.mozilla.org/en-US/docs/Web/API/console/profile>`_ and `console.profileEnd() <https://developer.mozilla.org/en-US/docs/Web/API/console/profileEnd>`_.
Save a profile
**************
To save a profile, click the link labeled "Save" in the Recordings pane:
.. image:: perf-save.png
:class: center
Load a profile
**************
To load a profile, click "Import..." and choose the file:
.. image:: perf-load.png
:class: center
Clear all loaded profiles
*************************
To clear all loaded profiles, click "Clear".
.. note::
If you do this, you'll lose any loaded profiles that you have not saved.
.. image:: perf-clear.png
:class: center
Select a tool
*************
To switch between the :doc:`Waterfall <../waterfall/index>`, :doc:`Call Tree <../call_tree/index>`, and :doc:`Flame Chart <../flame_chart/index>` tools, use the buttons in the toolbar:
.. image:: perf-select.png
:class: center
Configure markers displayed
***************************
To control which markers are shown in the :doc:`Waterfall <../waterfall/index>`, use the button in the toolbar:
.. image:: perf-markers.png
:class: center
Zoom in
*******
To zoom into a slice of the recording, select that slice in the recording overview:
.. image:: perf-zoom.png
:class: center

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Просмотреть файл

@ -2,49 +2,7 @@
Performance
===========
The Performance tool gives you insight into your site's general responsiveness, JavaScript and layout performance. With the Performance tool you create a recording, or profile, of your site over a period of time. The tool then shows you an :ref:`overview <performance-ui-tour-waterfall-overview>` of the things the browser was doing to render your site over the profile, and a graph of the :doc:`frame rate <frame_rate/index>` over the profile.
The documentation about the new performance took (also known as the Firefox
Profiler) can be found on the `Firefox Profiler website
<https://profiler.firefox.com/docs/>`_.
You get four sub-tools to examine aspects of the profile in more detail:
- the :doc:`Waterfall <waterfall/index>` shows the different operations the browser was performing, such as executing layout, JavaScript, repaints, and garbage collection
- the :doc:`Call Tree <call_tree/index>` shows the JavaScript functions in which the browser spent most of its time
- the :doc:`Flame Chart <flame_chart/index>` shows the JavaScript call stack over the course of the recording
- the :doc:`Allocations <allocations/index>` view shows the heap allocations made by your code over the course of the recording. This view only appears if you checked "Record Allocations" in the Performance tool settings.
.. raw:: html
<iframe width="560" height="315" src="https://www.youtube.com/embed/WBmttwfA_k8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<br/>
<br/>
Getting started
***************
:doc:`UI Tour <ui_tour/index>`
To find your way around the Performance tool, here's a quick tour of the UI.
:doc:`How to <how_to/index>`
Basic tasks: open the tool, create, save, load, and configure recordings
Components of the Performance tool
**********************************
:doc:`Frame rate <frame_rate/index>`
Understand your site's overall responsiveness.
:doc:`Call Tree <call_tree/index>`
Find bottlenecks in your site's JavaScript.
:doc:`Allocations <allocations/index>`
See the allocations made by your code over the course of the recording.
:doc:`Waterfall <waterfall/index>`
Understand the work the browser's doing as the user interacts with your site.
:doc:`Flame Chart <flame_chart/index>`
See which JavaScript functions are executing, and when, over the course of the recording.
Scenarios
*********
:doc:`Animating CSS properties <scenarios/animating_css_properties/index>`
Uses the Waterfall to understand how the browser updates a page, and how animating different CSS properties can affect performance.
:doc:`Intensive JavaScript <scenarios/intensive_javascript/index>`
Uses the frame rate and Waterfall tools to highlight performance problems caused by long-running JavaScript, and how using workers can help in this situation.

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 59 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 6.5 KiB

Просмотреть файл

@ -1,182 +0,0 @@
========================
Animating CSS properties
========================
The performance cost of animating a CSS property can vary from one property to another, and animating expensive CSS properties can result in `jank <https://developer.mozilla.org/en-US/docs/Glossary/Jank>`_ as the browser struggles to hit a smooth frame rate.
The :doc:`Frame rate <../../frame_rate/index>` and :doc:`Waterfall <../../waterfall/index>` can give you insight into the work the browser's doing in a CSS animation, to help diagnose performance problems.
With `CSS animations <https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations>`_ you specify a number of `keyframes <https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes>`_, each of which uses CSS to define the appearance of the element at a particular stage of the animation. The browser creates the animation as a transition from each keyframe to the next.
Compared with animating elements using JavaScript, CSS animations can be easier to create. They can also give better performance, as they give the browser more control over when to render frames, and to drop frames if necessary.
However, the performance cost of modifying a CSS property can vary from one property to another. Animating expensive CSS properties can result in `jank <https://developer.mozilla.org/en-US/docs/Glossary/Jank>`_ as the browser struggles to hit a smooth frame rate.
.. _performance-scenarios-animating_css_properties-rendering-waterfall:
The CSS rendering waterfall
***************************
The process the browser uses to update the page when a CSS property has changed can be described as a waterfall consisting of the following steps:
.. image:: css-rendering-waterfall.png
:class: center
- **Recalculate Style**: every time a CSS property for an element changes, the browser must recalculate computed styles.
- **Layout**: next, the browser uses the computed styles to figure out the position and geometry for the elements. This operation is labeled "layout" but is also sometimes called "reflow".
- **Paint**: finally, the browser needs to repaint the elements to the screen. One last step is not shown in this sequence: the page may be split into layers, which are painted independently and then combined in a process called "Composition".
This sequence needs to fit into a single frame, since the screen isn't updated until it is complete. It's commonly accepted that 60 frames per second is the rate at which animations will appear smooth. For a rate of 60 frames per second, that gives the browser 16.7 milliseconds to execute the complete flow.
.. _performance-scenarios-animating_css_properties-css-property-cost:
CSS property cost
*****************
In the context of the rendering waterfall, some properties are more expensive than others:
.. |br| raw:: html
<br/>
.. list-table::
:widths: 60 20 20
:header-rows: 1
* - Property type
- Cost
- Examples
* - Properties that affect an element's *geometry* or *position* trigger a style recalculation, a layout and a repaint.
- .. image:: recalculate-style.png
.. image:: layout.png
.. image:: paint.png
- `left <https://developer.mozilla.org/en-US/docs/Web/CSS/left>`_ |br|
`max-width <https://developer.mozilla.org/en-US/docs/Web/CSS/max-width>`_ |br|
`border-width <https://developer.mozilla.org/en-US/docs/Web/CSS/border-width>`_ |br|
`margin-left <https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left>`_ |br|
`font-size <https://developer.mozilla.org/en-US/docs/Web/CSS/font-size>`_
* - Properties that don't affect geometry or position, but are not rendered in their own layer, do not trigger a layout.
- .. image:: recalculate-style.png
.. image:: layout-faint.png
.. image:: paint.png
- `color <https://developer.mozilla.org/en-US/docs/Web/CSS/color>`_
* - Properties that are rendered in their own layer don't even trigger a repaint, because the update is handled in composition.
- .. image:: recalculate-style.png
.. image:: layout-faint.png
.. image:: paint-faint.png
- `transform <https://developer.mozilla.org/en-US/docs/Web/CSS/transform>`_ |br|
`opacity <https://developer.mozilla.org/en-US/docs/Web/CSS/opacity>`_
.. note::
The `CSS Triggers <https://csstriggers.com/>`_ website shows how much of the waterfall is triggered for each CSS property, with information for most CSS properties by browser engine.
An example: margin versus transform
***********************************
In this section we'll see how the :doc:`Waterfall </../../waterfall/index>` can highlight the difference between animating using `margin <https://developer.mozilla.org/en-US/docs/Web/CSS/margin>`_ and animating using `transform <https://developer.mozilla.org/en-US/docs/Web/CSS/transform>`_.
The intention of this scenario isn't to convince you that animating using ``margin`` is always a bad idea. It's to demonstrate how the tools can give you insight into the work the browser is doing to render your site, and how you can apply that insight to diagnose and fix performance problems.
If you want to play along, the demo website is `here <https://mdn.github.io/performance-scenarios/animation-transform-margin/index.html>`_. It looks like this:
.. image:: css-animations-demo.png
:class: center
It has two controls: a button to start/stop the animation, and a radio group to choose to animate using ``margin``, or to animate using ``transform``.
There are a number of elements, and we've added a `linear-gradient <https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient()>`_ background and a `box-shadow <https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow>`_ to each element, because they are both relatively expensive effects to paint.
Animating using margin
----------------------
Leaving the "Use margin" option set, start the animation, open the Performance tool, and make a recording. You'll only need to record a few seconds.
Open up the first recording. Exactly what you'll see depends a lot on your machine and system load, but it will be something like this:
.. image:: margin-recording.png
:class: center
This is showing three distinct views: (a) an overview of the Waterfall, (b) the frame rate, and (c) the timeline details.
.. _performance-scenarios-animation-css-properties-margin-waterfall-overview:
Waterfall overview
~~~~~~~~~~~~~~~~~~
.. image:: margin-timeline-overview.png
:class: center
This is showing a compressed view of the :doc:`Waterfall <../../waterfall/index>`. The predominance of green is telling us that :ref:`we're spending a lot of time painting <performance-waterfall-markers>`.
.. _performance-scenarios-animation-css-properties-margin-frame-rate:
Frame rate
~~~~~~~~~~
.. image:: margin-frame-rate.png
:class: center
This is showing :doc:`frame rate <../../frame_rate/index>`. Average frame rate here is 46.67fps, well below the target of 60fps. Worse, though, is that the frame rate is very jagged, with lots of dips into the twenties and teens. It's unlikely you'll see a smooth animation here, especially when you add in user interaction.
.. _performance-scenarios-animation-css-properties-margin-waterfall:
Waterfall
~~~~~~~~~
The rest of the recording shows the Waterfall view. If you scroll through this, you'll see a pattern like this:
.. image:: margin-timeline.png
:class: center
This is showing us the :ref:`rendering waterfall <performance-scenarios-animating_css_properties-rendering-waterfall>`. In each animation frame, we recalculate styles for every element, then perform a single layout, then a repaint.
You can see that paint especially is hurting performance here. In the screenshot above we've highlighted a paint operation, and the box on the right tells us it took 13.11ms. With only 16.7ms in our total budget, it's not surprising we are missing a consistently high frame rate.
You can experiment with this: try removing the box shadow :doc:`using the Page Inspector <../../../page_inspector/how_to/examine_and_edit_css/index>`, and see how that affects paint time. But next, we'll see how using `transform <https://developer.mozilla.org/en-US/docs/Web/CSS/transform>`_ instead of `margin <https://developer.mozilla.org/en-US/docs/Web/CSS/margin>`_ eliminates those expensive paints entirely.
Animating using transform
-------------------------
Now switch the radio button in the web page to "Use transform", and make a new recording. It will look something like this:
.. image:: transform-recording.png
:class: center
Waterfall overview
~~~~~~~~~~~~~~~~~~
.. image:: transform-timeline-overview.png
:class: center
Compared with :ref:`the version that uses margin <performance-scenarios-animation-css-properties-margin-waterfall-overview>`, we're seeing a lot less green and a lot more pink, which :ref:`could be either layout or style recalculation <performance-waterfall-markers>`.
Frame rate
~~~~~~~~~~
.. image:: transform-frame-rate.png
:class: center
Compared with :ref:`the version that uses margin <performance-scenarios-animation-css-properties-margin-frame-rate>`, this is looking pretty good. We're averaging nearly 60fps, and apart from one dip near the start, we're getting a consistently high frame rate.
Waterfall
~~~~~~~~~
The timeline view shows the reason for the improved frame rate. Compared with :ref:`the version that uses margin <performance-scenarios-animation-css-properties-margin-waterfall>`, we're not spending any time in layout or (more importantly in this case) in paint:
.. image:: transform-timeline.png
:class: center
In this case, using ``transform`` significantly improved the site's performance, and the performance tools were able to show how and why it did.

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 2.1 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 2.3 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 9.1 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 21 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.4 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 2.0 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.2 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 8.0 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.1 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 14 KiB

Просмотреть файл

@ -1,5 +0,0 @@
=========
Scenarios
=========
Performance scenarios

Просмотреть файл

@ -1,245 +0,0 @@
====================
Intensive JavaScript
====================
By default the browser uses a single thread to run all the JavaScript in your page as well as to perform layout, reflows, and garbage collection. This means that long-running JavaScript functions can block the thread, leading to an unresponsive page and a bad user experience.
You can use the :doc:`Frame rate <../../frame_rate/index>` and :doc:`Waterfall <../../waterfall/index>` tools to see when JavaScript is causing performance problems, and to single out the particular functions that need attention.
In this article we'll take an example site whose long-running JavaScript causes responsiveness problems, and apply two different approaches to fixing them. The first is to split long-running functions into pieces and use `requestAnimationFrame <https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame>`_ to schedule each piece, and the second is to run the whole function in a separate thread using a `web worker <https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers>`_.
If you want to play along you can find the demo website `here <https://mdn.github.io/performance-scenarios/js-worker/index.html>`_.
The demo website looks like this:
.. image:: js-worker-demo.png
:class: center
It has three controls:
- a radio button group to control how to run the JavaScript: as a single blocking operation in the main thread, as a series of smaller operations in the main thread using ``requestAnimationFrame()``, or in another thread using a worker.
- a button to run the JavaScript, labeled "Do pointless computations!".
- a button to start and stop some CSS animations. This just gives the browser some background tasks to perform.
Leaving the radio button set to "Use blocking call in main thread", make a recording:
- press the "Start animations" button
- start recording a performance profile
- press "Do pointless computations!" two or three times
- stop recording the profile
.. _performance-scenarios-intensive-javascript-js-blocking-overview:
Exactly what you see will vary from one machine to another, but it will be something like this:
.. image:: perf-js-blocking-overview.png
:class: center
The top half of this is the :ref:`waterfall overview <performance-ui-tour-waterfall-overview>`. It gives us a compressed view of the :doc:`Waterfall <../../waterfall/index>`, which tells us what kinds of operations the browser is doing during the recording. :ref:`The pink says that we are mostly performing CSS calculations and possibly reflow <performance-waterfall-markers>`: this is the CSS animation that's running throughout the profile. Then there are three solid blocks of orange, representing JavaScript execution, one for each time we pressed the button.
The bottom half, which is correlated with the timeline summary in time, shows :doc:`frame rate <../../frame_rate/index>`. We can see that frame rate is pretty healthy for most of the recording, but collapses completely whenever we press the button.
We can select one of these periods and have a closer look at it in the main Waterfall view:
.. image:: perf-js-blocking-waterfall.png
:class: center
Here, when we pressed the button, the browser ran a JavaScript function, or series of functions, that blocked the main thread for 71.73ms, or more than four times our frame budget.
Which function, though? By switching to the :doc:`Flame Chart <../../flame_chart/index>` view we can find out:
.. image:: perf-js-blocking-flame-chart.png
:class: center
This shows us the JS call stack at this point in the execution. At the top of the stack is a function called ``calculatePrimes()``, and we can see its filename and line number. Here's the code, together with its immediate caller:
.. code-block:: JavaScript
const iterations = 50;
const multiplier = 1000000000;
function calculatePrimes(iterations, multiplier) {
var primes = [];
for (var i = 0; i < iterations; i++) {
var candidate = i * (multiplier * Math.random());
var isPrime = true;
for (var c = 2; c <= Math.sqrt(candidate); ++c) {
if (candidate % c === 0) {
// not prime
isPrime = false;
break;
}
}
if (isPrime) {
primes.push(candidate);
}
}
return primes;
}
function doPointlessComputationsWithBlocking() {
var primes = calculatePrimes(iterations, multiplier);
pointlessComputationsButton.disabled = false;
console.log(primes);
}
We're just running a (very inefficient) primality test 50 times, for some quite large numbers.
Using requestAnimationFrame
***************************
In the first attempt at fixing this, we'll split up the function into a number of much smaller self-contained functions, and schedule each one using `requestAnimationFrame() <https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame>`_.
``requestAnimationFrame()`` tells the browser to run the given function in each frame, just before it performs a repaint. As long as each function is reasonably small, the browser should be able to keep inside its frame budget.
It's pretty simple to split up ``calculatePrimes()``: we will just calculate primality for each number in a separate function:
.. code-block:: javascript
function doPointlessComputationsWithRequestAnimationFrame() {
function testCandidate(index) {
// finishing condition
if (index == iterations) {
console.log(primes);
pointlessComputationsButton.disabled = false;
return;
}
// test this number
var candidate = index * (multiplier * Math.random());
var isPrime = true;
for (var c = 2; c <= Math.sqrt(candidate); ++c) {
if (candidate % c === 0) {
// not prime
isPrime = false;
break;
}
}
if (isPrime) {
primes.push(candidate);
}
// schedule the next
var testFunction = testCandidate.bind(this, index + 1);
window.requestAnimationFrame(testFunction);
}
var primes = [];
var testFunction = testCandidate.bind(this, 0);
window.requestAnimationFrame(testFunction);
}
Let's test this version out: select the radio button labeled "Use requestAnimationFrame" and capture another profile. This time, the recording should look something like this:
.. image:: perf-js-raf-overview.png
:class: center
This is exactly what we might have expected to see. Instead of :ref:`a single solid orange block <performance-scenarios-intensive-javascript-js-blocking-overview>`, each button-press shows up as a long sequence of very short orange blocks. The orange blocks appear one frame apart, and each one represents one of the functions called from ``requestAnimationFrame()``. Note that there are only two button-presses in this profile.
The function calls are interleaved with the pink blocks from the CSS animation, and each function is short enough that the browser can handle it without the overall frame rate dropping.
Using ``requestAnimationFrame`` worked to solve the responsiveness problem here, but there are a couple of potential problems with it:
- it can be difficult to split up a long-running function into separate self-contained functions. Even this very simple case produced more complex code.
- the split-up version takes much longer to run. In fact we can be quite precise about how long it takes: there are 50 iterations, and the browser is producing about 60 frames per second. So it will take almost a second to run all the computations, and that's visible in both the user experience and in the profile.
Using web workers
*****************
In this version we'll try to fix the problem using a web worker. Web workers enable you to run JavaScript in a separate thread. The main thread and the worker thread can't call each other directly, but communicate using an asynchronous messaging API.
The main thread code would look something like this:
.. code-block:: javascript
const iterations = 50;
const multiplier = 1000000000;
var worker = new Worker("js/calculate.js");
function doPointlessComputationsInWorker() {
function handleWorkerCompletion(message) {
if (message.data.command == "done") {
pointlessComputationsButton.disabled = false;
console.log(message.data.primes);
worker.removeEventListener("message", handleWorkerCompletion);
}
}
worker.addEventListener("message", handleWorkerCompletion, false);
worker.postMessage({
"multiplier": multiplier,
"iterations": iterations
});
}
The main difference here, compared with the original, is that we need to:
- create a worker
- send it a message when we are ready to calculate
- listen for a message called "done", which indicates that the worker has finished.
Then we need a new file "calculate.js", that looks like this:
.. code-block:: javascript
self.addEventListener("message", go);
function go(message) {
var iterations = message.data.iterations;
var multiplier = message.data.multiplier;
primes = calculatePrimes(iterations, multiplier);
self.postMessage({
"command":"done",
"primes": primes
});
}
function calculatePrimes(iterations, multiplier) {
var primes = [];
for (var i = 0; i < iterations; i++) {
var candidate = i * (multiplier * Math.random());
var isPrime = true;
for (var c = 2; c <= Math.sqrt(candidate); ++c) {
if (candidate % c === 0) {
// not prime
isPrime = false;
break;
}
}
if (isPrime) {
primes.push(candidate);
}
}
return primes;
}
In the worker, we have to listen for a message telling us to start, and send a "done" message back when we are done. The code that actually performs the computations is exactly the same as the original code.
So how does this version perform? Switch the radio button to "Use a worker", and capture a new profile. You should see something like this:
.. image:: perf-js-worker-overview.png
:class: center
In this profile we pushed the button three times. :ref:`Compared with the original <performance-scenarios-intensive-javascript-js-blocking-overview>`, each button-press is visible in the overview as two very short orange markers:
- the ``doPointlessComputationsInWorker()`` function that handles the click event and starts the worker's processing
- the ``handleWorkerCompletion()`` function that runs when the worker calls "done".
In between, the worker runs all the primality tests, and it doesn't seem to have any effect at all on the responsiveness of the main thread. This might seem unlikely, but because workers run in a separate thread, they can take advantage of multi-core processors, which a single-threaded web site can't.
The main limitation of web workers is that DOM APIs are not available to code running in a worker.

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 18 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 8.3 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 20 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 8.6 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 7.7 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 61 KiB

Просмотреть файл

@ -1,179 +0,0 @@
=======
UI Tour
=======
The performance tool's UI consists of 4 main pieces:
.. image:: perf-tool-pieces.png
:class: center
- :ref:`Toolbar <performance-ui-tour-toolbar>`
- :ref:`Recordings pane <performance-ui-tour-recordings-pane>`
- :ref:`Recording overview <performance-ui-tour-recording-overview>`
- :ref:`Details pane <performance-ui-tour-details-pane>`
- :ref:`Waterfall <performance-ui-tour-waterfall>`
- :ref:`Call Tree <performance-ui-tour-call-tree>`
- :ref:`Flame Chart <performance-ui-tour-flame-chart>`
.. _performance-ui-tour-toolbar:
Toolbar
*******
The toolbar contains buttons to:
- start and stop a recording
- import a recording you previously saved
- clear the Recordings pane. *Note that if you do this, you lose any recordings you have not saved.*
- filter the :ref:`markers <performance-waterfall-markers>` that are displayed in the Waterfall view
- switch the active tool in the :ref:`Details pane <performance-ui-tour-details-pane>`
- access the Settings popup
.. image:: perf-toolbar.png
:class: center
.. _performance-ui-tour-recordings-pane:
Recordings pane
***************
The recordings pane lists all the recordings you have loaded, including any you have made in this session and any you have imported.
.. image:: perf-recordings-pane.png
:class: center
At any given time, one recording is selected, and that recording is displayed in the rest of the tool. To select a different recording, click its entry in the pane. To save the recording as a JSON file click "Save".
.. _performance-ui-tour-recording-overview:
Recording overview
******************
This displays an overview of the entire recording, with the x-axis representing time.
.. image:: perf-overview.png
:class: center
It contains two elements: an overview of the Waterfall and a frame rate graph.
.. _performance-ui-tour-waterfall-overview:
Waterfall overview
------------------
This presents a compressed view of the :doc:`Waterfall <../waterfall/index>`:
.. image:: perf-waterfall-overview.png
:class: center
Recorded operations are color-coded using :ref:`the same scheme as in the main Waterfall view <performance-waterfall-markers>`.
Frame rate graph
----------------
The frame rate gives you an overview of the browser's responsiveness during the recording:
.. image:: perf-frame-rate.png
:class: center
See the separate article on :doc:`frame rate <../frame_rate/index>`.
Correlating events
------------------
Because these elements are synchronized, you can correlate events in one element with events in another.
For example, in the screenshot below a long-running paint operation (:ref:`shown as a green bar <performance-waterfall-markers>` in the waterfall overview) corresponds to a drop in the frame rate:
.. image:: perf-overview-correlation.png
:class: center
.. _performance-ui-tour-zooming-in:
Zooming in
----------
You can use the overview to select a slice of the recording to examine in more detail. Select a slice, and the main view will be updated to contain just the part selected. In the screenshot below we've selected that drop in the frame rate, and can see the long-running paint operation in more detail:
.. image:: perf-zoomed.png
:class: center
.. _performance-ui-tour-details-pane:
Details pane
************
The Details pane shows whichever tool is currently selected. To switch to a different tool, use the buttons in the :ref:`Toolbar <performance-ui-tour-toolbar>`.
.. _performance-ui-tour-waterfall:
Waterfall
---------
The Waterfall presents a view of the work the browser is doing during the recording: executing JavaScript, updating the CSS, updating the page layout, and performing repaints. The x-axis represents time, and the recorded operations are laid out as a waterfall, reflecting the serial nature of the browser's execution.
.. image:: perf-waterfall.png
:class: center
To learn much more about the Waterfall, see the separate :doc:`Waterfall <../waterfall/index>` page.
.. _performance-ui-tour-call-tree:
Call Tree
---------
The Call Tree is a sampling profiler for JavaScript running in the page. It periodically samples the state of the JavaScript engine, and records the stack for the code executing at the time the sample was taken. Statistically, the number of samples taken in which we were executing a particular function corresponds to the amount of time the browser is spending executing it, so you can identify bottlenecks in your code.
.. image:: perf-call-tree.png
:class: center
To learn much more about the Call Tree, see the separate :doc:`Call Tree <../call_tree/index>` page.
.. _performance-ui-tour-flame-chart:
Flame Chart
-----------
If the Call Tree tells you, statistically, which functions your site is spending most time executing across the whole recording, the Flame Chart tells you the call stack at any given point during the recording:
.. image:: perf-flame-chart.png
:class: center
To learn much more about the Flame Chart, see the separate :doc:`Flame Chart <../flame_chart/index>` page.
Allocations
-----------
The Allocations view is new in Firefox 46.
The Allocations view is like the Call Tree view, but for allocations: it shows you which functions in your page are allocating the most memory over the course of the profile.
.. image:: allocations-view-1.png
:class: center
The Allocations view only appears if you checked "Record Allocations" in the Performance tool settings, before recording a profile
To learn much more about the Allocations view, see the separate :doc:`Allocations <../allocations/index>` page.

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 38 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 30 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 6.5 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 37 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 8.2 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 5.6 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 48 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 18 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 2.7 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 20 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 574 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 817 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 852 B

Просмотреть файл

@ -1,395 +0,0 @@
=========
Waterfall
=========
The Waterfall gives you insight into the sorts of things the browser is doing as it runs your site or app. It's based on the idea that the things a browser does when running a site can be divided into various types - running JavaScript, updating layout, and so on - and that at any given point in time, the browser is doing one of those things.
So if you see a sign of a performance problem - a drop in the frame rate, for example - you can go to the Waterfall to see what the browser was doing at that point in the recording.
.. image:: perf-waterfall.png
:class: center
Along the X-axis is time. Recorded operations, called markers, are shown as horizontal bars, laid out in a waterfall to reflect the serial nature of the browser's execution.
When a marker is selected you'll see more information about it in a sidebar on the right.This includes the marker's duration and some more information that's specific to the :ref:`marker type <performance-waterfall-markers>`.
.. _performance-waterfall-markers:
Markers
*******
The markers for operations are color-coded and labeled. The following operations are recorded:
.. |br| raw:: html
<br/>
.. list-table::
:widths: 40 20 40
:header-rows: 1
* - Name and description
- Color
- Detailed Information
* - **DOM Event** |br| |br|
JavaScript code that's executed in response to a DOM event.
- .. image:: orange.png
- **Event Type**
For example, "click" or "message".
**Event Phase**
For example, "Target" or "Capture".
* - JavaScript functions executed in the page are labeled with the reason the function was called: |br| |br|
**Script Tag** |br|
**setInterval** |br|
**setTimeout** |br|
**requestAnimationFrame** |br|
**Promise Callback** |br|
**Promise Init** |br|
**Worker** |br|
**JavaScript URI** |br|
**Event Handler** |br|
- .. image:: orange.png
- **Stack**
Call stack, with links to functions.
* - **Parse HTML** |br| |br|
Time spent parsing the page's HTML.
- .. image:: orange.png
- **Stack**
Call stack, with links to functions.
* - **Parse XML** |br| |br|
Time spent parsing the page's XML.
- .. image:: orange.png
- **Stack**
Call stack, with links to functions.
* - **Recalculate Style** |br| |br|
Calculating the computed styles that apply to page elements.
- .. image:: purple.png
- **Restyle Hint** |br| |br|
A string indicating what kind of restyling is needed. The hint may be any of:
- Self
- Subtree
- LaterSiblings
- CSSTransitions
- CSSAnimations
- SVGAttrAnimations
- StyleAttribute
- StyleAttribute_Animations
- Force
- ForceDescendants
* - **Layout** |br| |br|
Calculating the position and size of page elements. This operation is sometimes called "reflow".
- .. image:: purple.png
-
* - **Paint** |br| |br|
Drawing pixels to the screen.
- .. image:: green.png
-
* - **Garbage Collection** |br| |br|
:ref:`Garbage collection event <performance-waterfall-garbage_collection>`. Non-incremental GC events are labeled "(Non-incremental)".
- .. image:: red.png
- **Reason**
A string indicating the reason GC was performed.
|br|
**Non-incremental Reason**
If the GC event was non-incremental, the string indicates the reason non-incremental GC was performed.
New in Firefox 46: if the GC event was caused by allocation pressure, a link appears, labeled "Show Allocation Triggers". Click the link to see the allocation profile leading up to this GC event. |br| |br|
See :ref:`Allocations and Garbage Collection <performance-allocations-and-garbage-collection>` for more details.
* - **Cycle Collection** |br| |br|
Reclaiming C++ reference-counted data structures. |br| |br|
Like garbage collection, but for C++ objects. See `Kyle Huey's blog post about cycle collection <https://blog.kylehuey.com/post/27564411715/cycle-collection>`_.
- .. image:: red.png
- **Type**
Always "Collect".
* - **CC Graph Reduction** |br| |br|
Preparation/pre-optimization for Cycle Collection.
- .. image:: red.png
- **Type**
Always "ForgetSkippable".
* - **Console** |br| |br|
The period between matching calls to ``console.time()`` and ``console.timeEnd()``.
- .. image:: gray.png
- **Timer name**
The argument passed to the ``console`` functions.
**Stack at start**
Call stack ``console.time()``, with links to functions.
**Stack at End**
(New in Firefox 41). Call stack at ``console.timeEnd()``. If this is inside a callback from a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, this will also show the :ref:`Async stack <performance-waterfall-async-stack>`.
* - **Timestamp** |br| |br|
A single call to `console.timeStamp() <https://developer.mozilla.org/en-US/docs/Web/API/console/timeStamp>`_.
- .. image:: blue.png
- **Label**
The argument passed to ``timeStamp()``.
* - **DOMContentLoaded** |br| |br|
The document's `DOMContentLoaded <https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event>`_ event.
- .. image:: red.png
-
* - **Load** |br| |br|
The document's `load <https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event>`_ event.
- .. image:: blue.png
-
* - **Worker event in main thread** |br| |br|
Shown when the main thread sends a message to a worker, or receives a message from a worker.
- .. image:: orange.png
- **Serialize data on the main thread**
The main thread is serializing a message to be sent to the worker.
**Deserialize data on the main thread**
The main thread is deserializing a message received from the worker.
* - **Worker event in worker thread**
Shown when a worker receives a message from the main thread, or sends a message to the main thread.
- .. image:: orange2-hollow.png
- One of: |br| |br|
**Serialize data in Worker**
The worker is serializing a message to be sent to the main thread.
**Deserialize data in Worker**
The worker is deserializing a message received from the main thread.
The markers, and their colors, are the same in the Waterfall tool as in the :ref:`Waterfall overview <performance-ui-tour-waterfall-overview>`, making is easy to correlate from one to the other.
Filtering markers
-----------------
You can control which markers are displayed using a button in the :ref:`Toolbar <performance-ui-tour-toolbar>`:
.. image:: perf-markers.png
:class: center
Waterfall patterns
******************
Exactly what you'll see in the Waterfall is very dependent on the kind of thing your site is doing: JavaScript-heavy sites will have a lot of orange, while visually dynamic sites will have a lot of purple and green. But there are common patterns which can alert you to possible performance problems.
Rendering waterfall
-------------------
One pattern that you'll often see in the Waterfall view is something like this:
.. image:: perf-timeline-waterfall.png
:class: center
This is a visualization of the basic algorithm the browser uses to update the page in response to some event:
1. **JavaScript Function Call**: some event - for example, a DOM event - causes some JavaScript in the page to run. The JavaScript changes some of the page's DOM or CSSOM.
2. **Recalculate Style**: if the browser thinks the computed styles for page elements have changed, it must then recalculate them.
3. **Layout**: next, the browser uses the computed styles to figure out the position and geometry for the elements. This operation is labeled "layout" but is also sometimes called "reflow".
4. **Paint**: finally, the browser needs to repaint the elements to the screen. One last step is not shown in this sequence: the page may be split into layers, which are painted independently and then combined in a process called "Composition".
This sequence needs to fit into a single frame, since the screen isn't updated until it is complete. It's commonly accepted that 60 frames per second is the rate at which animations will appear smooth. For a rate of 60 frames per second, that gives the browser 16.7 milliseconds to execute the complete flow.
Importantly for responsiveness, the browser doesn't always have to go through every step:
- `CSS animations <https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations>`_ update the page without having to run any JavaScript.
- Not all CSS property changes cause a reflow. Changing properties that can alter an object's geometry and position, such as `width <https://developer.mozilla.org/en-US/docs/Web/CSS/width>`_, `display <https://developer.mozilla.org/en-US/docs/Web/CSS/display>`_, `font-size <https://developer.mozilla.org/en-US/docs/Web/CSS/font-size>`_, or `top <https://developer.mozilla.org/en-US/docs/Web/CSS/top>`_, will cause a reflow. However, changing properties that don't alter geometry or position, such as `color <https://developer.mozilla.org/en-US/docs/Web/CSS/color>`_ or `opacity <https://developer.mozilla.org/en-US/docs/Web/CSS/opacity>`_, will not.
- Not all CSS property changes cause a repaint. In particular, if you animate an element using the `transform <https://developer.mozilla.org/en-US/docs/Web/CSS/transform>`_ property, the browser will use a separate layer for the transformed element, and doesn't even have to repaint when the element is moved: the new position of the element is handled in composition.
The :doc:`Animating CSS properties <../scenarios/animating_css_properties/index>` article shows how animating different CSS properties can give different performance outcomes, and how the Waterfall can help signal that.
Blocking JavaScript
-------------------
By default, a site's JavaScript is executed in the same thread that the browser uses for layout updates, repaints, DOM events, and so on. This means that long-running JavaScript functions can cause unresponsiveness (jank): animations may not be smooth, or the site might even freeze.
Using the frame rate tool and the Waterfall together, it's easy to see when long-running JavaScript is causing responsiveness problems. In the screenshot below, we've zoomed in on a JS function that's caused a drop in the frame rate:
.. image:: perf-js-blocking-waterfall.png
:class: center
The :doc:`Intensive JavaScript <../scenarios/intensive_javascript/index>` article shows how the Waterfall can highlight responsiveness problems caused by long JavaScript functions, and how you can use asynchronous methods to keep the main thread responsive.
Expensive paints
----------------
Some paint effects, such as `box-shadow <https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow>`_, can be expensive, especially if you are applying them in a transition where the browser has to calculate them in every frame. If you're seeing drops in the frame rate, especially during graphically-intensive operations and transitions, check the Waterfall for long green markers.
.. _performance-waterfall-garbage_collection:
Garbage collection
------------------
Red markers in the Waterfall represent garbage collection (GC) events, in which `SpiderMonkey <https://spidermonkey.dev/>`_ (the JavaScript engine in Firefox) walks the heap looking for memory that's no longer reachable and subsequently releasing it. GC is relevant to performance because while it's running the JavaScript engine must be paused, so your program is suspended and will be completely unresponsive.
To help reduce the length of pauses, SpiderMonkey implements *incremental GC*: this means that it can perform garbage collection in fairly small increments, letting the program run in between. Sometimes, though, it needs to perform a full non-incremental collection, and the program has to wait for it to finish.
In trying to avoid GC events, and especially non-incremental GC events, it's wise not to try to optimize for the specific implementation of the JavaScript engine. SpiderMonkey uses a complex set of heuristics to determine when GC is needed, and when non-incremental GC in particular is needed. In general, though:
- GC is needed when a lot of memory is being allocated
- non-incremental GC is usually needed when the memory allocation rate is high enough that SpiderMonkey may run out of memory during incremental GC
When the Waterfall records a GC marker it indicates:
- whether the GC was incremental or not
- the reason the GC was performed
- if the GC was non-incremental, the reason it was non-incremental
- starting in Firefox 46, if the GC event was caused by allocation pressure, a link appears, labeled "Show Allocation Triggers". Click the link to see the allocation profile leading up to this GC event. See :ref:`Allocations and Garbage Collection <performance-allocations-and-garbage-collection>` for more details.
Adding markers with the console API
***********************************
Two markers are directly controlled by `console API <https://developer.mozilla.org/en-US/docs/Web/API/console>`_ calls: "Console" and "Timestamp".
Console markers
---------------
These enable you to mark a specific section of the recording.
To make a console marker, call ``console.time()`` at the start of the section, and ``console.timeEnd()`` at the end. These functions take an argument which is used to name the section.
For example, suppose we have code like this:
.. code-block:: JavaScript
var iterations = 70;
var multiplier = 1000000000;
function calculatePrimes() {
console.time("calculating...");
var primes = [];
for (var i = 0; i < iterations; i++) {
var candidate = i * (multiplier * Math.random());
var isPrime = true;
for (var c = 2; c <= Math.sqrt(candidate); ++c) {
if (candidate % c === 0) {
// not prime
isPrime = false;
break;
}
}
if (isPrime) {
primes.push(candidate);
}
}
console.timeEnd("calculating...");
return primes;
}
The Waterfall's output will look something like this:
.. image:: perf-console-time.png
:class: center
The marker is labeled with the argument you passed to ``console.time()``, and when you select the marker, you can see the program stack in the right-hand sidebar.
.. _performance-waterfall-async-stack:
Async stack
~~~~~~~~~~~
New in Firefox 41.
Starting in Firefox 41, the right-hand sidebar will also show the stack at the end of the period: that is, at the point ``console.timeEnd()`` was called. If ``console.timeEnd()`` was called from the resolution of a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, it will also display "(Async: Promise)", under which it will show the "async stack": that is, the call stack at the point the promise was made.
For example, consider code like this:
.. code-block:: JavaScript
var timerButton = document.getElementById("timer");
timerButton.addEventListener("click", handleClick, false);
function handleClick() {
console.time("timer");
runTimer(1000).then(timerFinished);
}
function timerFinished() {
console.timeEnd("timer");
console.log("ready!");
}
function runTimer(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
The Waterfall will display a marker for the period between ``time()`` and ``timeEnd()``, and if you select it, you'll see the async stack in the sidebar:
.. image:: async-stack.png
:class: center
Timestamp markers
-----------------
Timestamps enable you to mark an instant in the recording.
To make a timestamp marker, call `console.timeStamp() <https://developer.mozilla.org/en-US/docs/Web/API/console/timeStamp>`_. You can pass an argument to label the timestamp.
For example, suppose we adapt the code above to make a timestamp every 10 iterations of the loop, labeled with the iteration number:
.. code-block:: JavaScript
var iterations = 70;
var multiplier = 1000000000;
function calculatePrimes() {
console.time("calculating...");
var primes = [];
for (var i = 0; i < iterations; i++) {
if (i % 10 == 0) {
console.timeStamp(i.toString());
}
var candidate = i * (multiplier * Math.random());
var isPrime = true;
for (var c = 2; c <= Math.sqrt(candidate); ++c) {
if (candidate % c === 0) {
// not prime
isPrime = false;
break;
}
}
if (isPrime) {
primes.push(candidate);
}
}
console.timeEnd("calculating...");
return primes;
}
In the Waterfall you'll now see something like this:
.. image:: perf-timestamp.png
:class: center

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 852 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 592 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 32 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 20 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 9.3 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 37 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 20 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 852 B

Двоичные данные
devtools/docs/user/performance/waterfall/red.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 574 B

Просмотреть файл

@ -1,9 +0,0 @@
======================
JavaScript flame chart
======================
Determining why CPUs are busy is a routine task for performance analysis, which often involves profiling stack traces. Profiling by sampling at a fixed rate is a coarse but effective way to see which code-paths are hot (busy on-CPU). It usually works by creating a timed interrupt that collects the current program counter, function address, or entire stack back trace, and translates these to something human readable when printing a summary report.
Profiling data can be thousands of lines long, and difficult to comprehend. *Flame graphs* are a visualization for sampled stack traces, which allows hot code-paths to be identified quickly. See the `Flame Graphs <http://www.brendangregg.com/flamegraphs.html>`_ main page for uses of this visualization other than CPU profiling.
Flame Graphs can work with any CPU profiler on any operating system. My examples here use Linux perf_events, DTrace, SystemTap, and ktap. See the `Updates <http://www.brendangregg.com/flamegraphs.html#Updates>`_ list for other profiler examples, and `github <https://github.com/brendangregg/FlameGraph>`_ for the flame graph software.