Skip to content

Conversation

@pablogsal
Copy link
Member

@pablogsal pablogsal commented Oct 27, 2025

Introduce a new --heatmap output format that provides line-by-line
execution visualization. The heatmap shows:

  • Color-coded execution intensity for each line (cold → warm → hot → very hot)
  • Inline sample counts and percentages per line
  • Per-file statistics (total samples, hottest line)
  • Interactive call graph navigation with caller/callee buttons
  • Module type badges (stdlib, site-packages, project code)

Unlike flamegraphs which show call stacks and time distribution, heatmaps
excel at identifying hot code paths within files, understanding line-level
execution patterns, and navigating through call relationships.

@pablogsal
Copy link
Member Author

CC @ambv

Introduce a new --heatmap output format that provides line-by-line
execution visualization. The heatmap shows:

- Color-coded execution intensity for each line (cold → warm → hot → very hot)
- Inline sample counts and percentages per line
- Per-file statistics (total samples, hottest line)
- Interactive call graph navigation with caller/callee buttons
- Module type badges (stdlib, site-packages, project code)

Unlike flamegraphs which show call stacks and time distribution, heatmaps
excel at identifying hot code paths within files, understanding line-level
execution patterns, and navigating through call relationships.
Copy link
Member

@savannahostrowski savannahostrowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this is so cool! I left a couple of comments, but also wanted to mention that I really loved that you added a minimap to show hotspots and the permalinking on line click; so nice for jumping around and sharing results.

</div>
<div class="stat-card">
<span class="stat-value"><!-- TOTAL_SAMPLES --></span>
<span class="stat-label">Total Samples</span>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using "samples" twice in the same view here - once for total samples (i.e., number of snapshots taken during profiling) and the other "samples" to mean the number of lines recorded in that file.

This can be a bit confusing, since file samples can exceed the total number of samples. One idea to help disambiguate might be to add a tooltip or subtext on file samples to say something like "Line samples captured (sum across call stacks)", or rename one of them?

Comment on lines +63 to +64
<th onclick="sortTable(5)" style="text-align: right;">% of Total ⇅</th>
<th style="text-align: left;">Intensity</th>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if I was sleepy or what but I genuinely had to use brainpower ™️ to understand these columns.

IIUC, these two columns show the same data in different formats. It was not initially obvious to me that % of total wasn't intended to sum to 100% and that the % and bar are actually relative to the hottest file (which should always equal 100%). I feel like my brain expected the bars below the top file to be a proportion of a whole.

A thought here might be to merge the columns into a single column called "Intensity" and then show the percentage number with a coloured background using the same blue --> red heatmap. We could also add a note in the header that this is really the % relative to the hottest file.

module_name = html.escape(stat['module_name'])
module_type = stat['module_type']
badge_class = f"badge-{module_type}"
bar_width = min(100, stat['percentage'] * 2) # Scale for visibility
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this calculation isn't quite right? It looks like a file with 46.15% intensity is actually like 92% full because of the * 2

Image

filename = filename or f"flamegraph.{pid}.html"
case "heatmap":
collector = HeatmapCollector(skip_idle=skip_idle)
filename = filename or f"heatmap_{pid}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if folks will want to have this saved by timestamp to compare historical runs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants