Skip to content

Commit

Permalink
Rename flamegraph "Invert" button
Browse files Browse the repository at this point in the history
We've adding a `--inverted` mode to `memray flamegraph` causing stacks
to be added to the flame graph in reverse order, so that the children of
the root are functions that performed allocations and the leaves are
thread entry points. Because of this change, we need a different name
for the "Invert" button that flips the entire flame graph upside down.

This commit introduces a new toggle button for switching between our
default "icicle graph" view (with the root at the top and allocations
dangling from it) and the traditional "flame graph" view (with the root
at the bottom and allocations rising up from it). The toggle button also
gives a visual indication of what mode you're in.

Signed-off-by: Matt Wozniski <[email protected]>
  • Loading branch information
godlygeek authored and pablogsal committed Sep 18, 2023
1 parent 5a6c62a commit d769830
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 18 deletions.
Binary file added docs/_static/images/icicle_flame_toggle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/_static/images/invert_button.png
Binary file not shown.
29 changes: 17 additions & 12 deletions docs/flamegraph.rst
Original file line number Diff line number Diff line change
Expand Up @@ -196,19 +196,24 @@ checkbox:
Note that allocations in these frames will still be accounted for
in parent frames, even if they're hidden.

Inverted View
-----------------

Although the flame graphs explained above show the calling functions below
and memory allocating functions above, flame graphs can be inverted
so that the calling functions are at the top, while memory allocating
functions are at the bottom. In this view, look for wide ceilings
instead of wide plateaus to find functions with the largest allocation
of memory.

To invert the flame graph, press the *Invert* button:
Flames versus Icicles
---------------------

.. image:: _static/images/invert_button.png
The flame graphs explained above show each function above its caller,
with the root at the bottom. This is what's traditionally called
a "flame graph", because the wide base with narrowing columns above it
looks sort of like a burning log with flames leaping into the air above
it. Memray also supports what's sometimes called an "icicle graph",
which has the root at the top. In an icicle graph, each function is
below its caller, and there is a wide ceiling that thinner columns
descend from, like icicles hanging from a roof. Whichever of these modes
you choose, the data shown in the table is the same, just mirrored
vertically.

You can switch between showing a flame graph and an icicle graph with
this toggle button:

.. image:: _static/images/icicle_flame_toggle.png
:align: center

.. _memory-leaks-view:
Expand Down
3 changes: 2 additions & 1 deletion src/memray/reporters/assets/flamegraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ function main() {
}

// Setup event handlers
document.getElementById("invertButton").onclick = onInvert;
document.getElementById("icicles").onchange = onInvert;
document.getElementById("flames").onchange = onInvert;
document.getElementById("resetZoomButton").onclick = onResetZoom;
document.getElementById("resetThreadFilterItem").onclick = onFilterThread;
let hideUninterestingCheckBox = document.getElementById("hideUninteresting");
Expand Down
5 changes: 4 additions & 1 deletion src/memray/reporters/assets/flamegraph_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,11 @@ export function handleFragments() {

// For the invert button
export function onInvert() {
chart.inverted(!chart.inverted());
chart.inverted(this === document.getElementById("icicles"));
chart.resetZoom(); // calls onClick

// Hide the tooltip for the radio button that was just clicked.
$('[data-toggle="tooltip"]').tooltip("hide");
}

export function onResetZoom() {
Expand Down
3 changes: 2 additions & 1 deletion src/memray/reporters/assets/temporal_flamegraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,8 @@ function main() {
}

// Setup event handlers
document.getElementById("invertButton").onclick = onInvert;
document.getElementById("icicles").onchange = onInvert;
document.getElementById("flames").onchange = onInvert;
document.getElementById("resetZoomButton").onclick = onResetZoom;
document.getElementById("resetThreadFilterItem").onclick = onFilterThread;
let hideUninterestingCheckBox = document.getElementById("hideUninteresting");
Expand Down
8 changes: 8 additions & 0 deletions src/memray/reporters/templates/assets/flamegraph.css
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,11 @@
background-color: rgba(0, 0, 0, 0.5); /* semi-transparent black */
z-index: 99; /* make sure it's on top of other elements */
}

.flamegraph-icon {
display: flex;
align-items: center;
justify-content: center;
}

.flipped svg { transform: scale(1,-1); }
2 changes: 1 addition & 1 deletion src/memray/reporters/templates/assets/flamegraph.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

23 changes: 22 additions & 1 deletion src/memray/reporters/templates/flamegraph.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,29 @@
title="Hide frames related to the Python import system" >
<label class="form-check-label text-white bg-dark">Hide Import System Frames</label>
</div>
<div class="btn-group btn-group-toggle mr-3" data-toggle="buttons">
<label class="btn btn-outline-light shadow-none" data-container="body" data-toggle="tooltip" title="Enable flame graph mode: functions above their callers with the root at the bottom">
<input type="radio" name="flames/icicles" id="flames" autocomplete="off">
<div class="flamegraph-icon flipped">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M 1 1 h 22 Z M 11 6 h 10 Z M 1 6 h 7 Z M 11 11 h 7 Z M 1 11 h 4 Z M 11 16 h 4 Z M 1 16 h 2 Z M 11 21 h 2 Z"/>
</svg>
</div>
&nbsp;
Flames
</label>
<label class="btn btn-outline-light active shadow-none" data-container="body" data-toggle="tooltip" title="Enable icicle graph mode: functions below their callers with the root at the top">
<input type="radio" name="flames/icicles" id="icicles" autocomplete="off" checked/>
Icicles
&nbsp;
<div class="flamegraph-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M 1 1 h 22 Z M 11 6 h 10 Z M 1 6 h 7 Z M 11 11 h 7 Z M 1 11 h 4 Z M 11 16 h 4 Z M 1 16 h 2 Z M 11 21 h 2 Z"/>
</svg>
</div>
</label>
</div>
<button id="resetZoomButton" class="btn btn-outline-light mr-3">Reset Zoom</button>
<button id="invertButton" class="btn btn-outline-light mr-3">Invert</button>
{% endblock %}

{% block content %}
Expand Down

0 comments on commit d769830

Please sign in to comment.