Skip to content

Commit 65528db

Browse files
Add differential flame graph
Differential flame graphs compare two profiling runs and highlight where performance has changed. This makes it easier to detect regressions introduced by code changes and to verify that optimizations have the intended effect. The visualization renders the current profile with frame widths representing current time consumption. Color is then applied to show the difference relative to the baseline profile: red gradients indicate regressions, while blue gradients indicate improvements. Some call paths may disappear entirely between profiles. These are referred to as elided stacks and occur when optimizations remove code paths or when certain branches stop executing. When elided stacks are present, an "Elided" toggle is displayed, allowing the user to switch between the main differential view and a view showing only the removed paths.
1 parent 665c1db commit 65528db

File tree

8 files changed

+1014
-51
lines changed

8 files changed

+1014
-51
lines changed

Doc/library/profiling.sampling.rst

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,47 @@ at the top indicate functions that consume significant time either directly
10031003
or through their callees.
10041004

10051005

1006+
Differential flame graphs
1007+
~~~~~~~~~~~~~~~~~~~~~~~~~
1008+
1009+
Differential flame graphs compare two profiling runs to highlight where
1010+
performance changed. This helps identify regressions introduced by code changes
1011+
and validate that optimizations achieved their intended effect::
1012+
1013+
# Capture baseline profile
1014+
python -m profiling.sampling run --binary -o baseline.bin script.py
1015+
1016+
# After modifying code, generate differential flamegraph
1017+
python -m profiling.sampling run --diff-flamegraph baseline.bin -o diff.html script.py
1018+
1019+
The visualization draws the current profile with frame widths showing current
1020+
time consumption, then applies color to indicate how each function changed
1021+
relative to the baseline.
1022+
1023+
**Color coding**:
1024+
1025+
- **Red**: Functions consuming more time (regressions). Lighter shades indicate
1026+
modest increases, while darker shades show severe regressions.
1027+
1028+
- **Blue**: Functions consuming less time (improvements). Lighter shades for
1029+
modest reductions, darker shades for significant speedups.
1030+
1031+
- **Gray**: Minimal or no change.
1032+
1033+
- **Purple**: New functions not present in the baseline.
1034+
1035+
Frame colors indicate changes in **direct time** (time when the function was at
1036+
the top of the stack, actively executing), not cumulative time including callees.
1037+
Hovering over a frame shows comparison details including baseline time, current
1038+
time, and the percentage change.
1039+
1040+
Some call paths may disappear entirely between profiles. These are called
1041+
**elided stacks** and occur when optimizations eliminate code paths or certain
1042+
branches stop executing. If elided stacks are present, an elided toggle appears
1043+
allowing you to switch between the main differential view and an elided-only
1044+
view that shows just the removed paths (colored deep red).
1045+
1046+
10061047
Gecko format
10071048
------------
10081049

@@ -1488,6 +1529,10 @@ Output options
14881529

14891530
Generate self-contained HTML flame graph.
14901531

1532+
.. option:: --diff-flamegraph <baseline.bin>
1533+
1534+
Generate differential flamegraph comparing to a baseline binary profile.
1535+
14911536
.. option:: --gecko
14921537

14931538
Generate Gecko JSON format for Firefox Profiler.

Lib/profiling/sampling/_flamegraph_assets/flamegraph.css

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,29 @@
55
This file extends the shared foundation with flamegraph-specific styles.
66
========================================================================== */
77

8+
/* --------------------------------------------------------------------------
9+
Differential Flamegraph
10+
-------------------------------------------------------------------------- */
11+
12+
:root {
13+
/* Regression colors */
14+
--diff-regression-deep: #d32f2f;
15+
--diff-regression-medium: #e57373;
16+
--diff-regression-light: #ef9a9a;
17+
--diff-regression-verylight: #ffcdd2;
18+
19+
/* Improvement colors */
20+
--diff-improvement-deep: #1976d2;
21+
--diff-improvement-medium: #42a5f5;
22+
--diff-improvement-light: #64b5f6;
23+
--diff-improvement-verylight: #90caf9;
24+
25+
/* Other differential colors */
26+
--diff-neutral: #bdbdbd;
27+
--diff-new: #9575cd;
28+
--diff-elided: #d32f2f;
29+
}
30+
831
/* --------------------------------------------------------------------------
932
Layout Overrides (Flamegraph-specific)
1033
-------------------------------------------------------------------------- */
@@ -277,7 +300,9 @@ body.resizing-sidebar {
277300
/* View Mode Section */
278301
.view-mode-section .section-content {
279302
display: flex;
280-
justify-content: center;
303+
flex-direction: column;
304+
gap: 10px;
305+
align-items: center;
281306
}
282307

283308
/* Collapsible sections */
@@ -815,6 +840,41 @@ body.resizing-sidebar {
815840
color: var(--accent);
816841
}
817842

843+
.tooltip-diff {
844+
margin-top: 12px;
845+
padding-top: 12px;
846+
border-top: 1px solid var(--border);
847+
}
848+
849+
.tooltip-diff-title {
850+
font-size: 11px;
851+
font-weight: 600;
852+
color: var(--accent);
853+
margin-bottom: 8px;
854+
}
855+
856+
.tooltip-diff-row {
857+
display: grid;
858+
grid-template-columns: auto 1fr;
859+
gap: 4px 14px;
860+
font-size: 12px;
861+
margin-bottom: 4px;
862+
}
863+
864+
.tooltip-diff-row.regression .tooltip-stat-value {
865+
color: rgb(220, 60, 60);
866+
font-weight: 700;
867+
}
868+
869+
.tooltip-diff-row.improvement .tooltip-stat-value {
870+
color: rgb(60, 120, 220);
871+
font-weight: 700;
872+
}
873+
874+
.tooltip-diff-row.neutral .tooltip-stat-value {
875+
color: var(--text-secondary);
876+
}
877+
818878
.tooltip-source {
819879
margin-top: 10px;
820880
padding-top: 10px;
@@ -989,7 +1049,8 @@ body.resizing-sidebar {
9891049
Flamegraph-Specific Toggle Override
9901050
-------------------------------------------------------------------------- */
9911051

992-
#toggle-invert .toggle-track.on {
1052+
#toggle-invert .toggle-track.on,
1053+
#toggle-elided .toggle-track.on {
9931054
background: #8e44ad;
9941055
border-color: #8e44ad;
9951056
box-shadow: 0 0 8px rgba(142, 68, 173, 0.3);

0 commit comments

Comments
 (0)