◐ Shell
clean mode source ↗

gh-138122: Add differential flame graph by ivonastojanovic · Pull Request #145785 · python/cpython

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.

@ivonastojanovic ivonastojanovic changed the title Add differential flame graph gh-138122: Add differential flame graph

Mar 10, 2026

@ivonastojanovic

pablogsal

Use four gradients consistently for both regressions and
improvements. Also avoid calling
getComputedStyle(document.documentElement) on every frame, cache
the values like we do for the heatmap, since doing this per frame
can be expensive for large profiles.
Since baseline and current self time are shown in ms, the diff
should also be displayed in ms instead of samples.
We were determining the selected data and applying
filtering/processing inside each toggle handler, which led to
inconsistencies (e.g. thread filtering) and missed cases. This
approach also won’t scale well as we add more toggles. Instead,
introduce a single centralized function that returns the active
flamegraph data and use it consistently for all updates and
processing.
Clean up tests by extracting repeated logic (resolving function
names and finding child nodes by name) into helper functions. Also
add a test that doesn’t mock BinaryCollector to cover the full
round trip.
Use purple (with gradients) for both removed and new functions to
unify these “out-of-band” cases under a single visual language,
meaning no direct comparison is available. This keeps them clearly
separate from the red/blue performance axis and simplifies the
legend: “purple = this function has no counterpart in the other
profile.”
                                                                                                                                                           Opcodes from multiple call paths were silently dropped, only the
first path's opcodes were kept. Now they're summed correctly when
nodes merge.

@ivonastojanovic

picnixz

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>

picnixz

maurycy added a commit to maurycy/cpython that referenced this pull request

Mar 30, 2026

clin1234 pushed a commit to clin1234/cpython that referenced this pull request

Apr 16, 2026
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.

Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>

ljfp pushed a commit to ljfp/cpython that referenced this pull request

Apr 25, 2026
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.

Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>