Skip to content

Commit c79f2a4

Browse files
committed
gh-154032: Scale elided flamegraph values
1 parent 1b3020e commit c79f2a4

2 files changed

Lines changed: 35 additions & 0 deletions

File tree

Lib/profiling/sampling/stack_collector.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,7 @@ def _build_elided_flamegraph(self, baseline_stats, scale):
764764
if not self._extract_elided_nodes(baseline_data, path=()):
765765
return None
766766

767+
self._scale_flamegraph_values(baseline_data, scale)
767768
self._add_elided_metadata(baseline_data, baseline_stats, scale, path=())
768769

769770
# Merge only profiling metadata, not thread-level stats
@@ -777,6 +778,13 @@ def _build_elided_flamegraph(self, baseline_stats, scale):
777778

778779
return baseline_data
779780

781+
def _scale_flamegraph_values(self, node, scale):
782+
"""Express flamegraph values in units of the current sample interval."""
783+
node["value"] = node.get("value", 0) * scale
784+
node["self"] = node.get("self", 0) * scale
785+
for child in node.get("children", ()):
786+
self._scale_flamegraph_values(child, scale)
787+
780788
def _extract_elided_nodes(self, node, path):
781789
"""Remove non-elided nodes and recalculate values bottom-up."""
782790
if not node:

Lib/test/test_profiling/test_sampling_profiler/test_collectors.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,33 @@ def test_diff_flamegraph_scale_factor_uses_sample_intervals(self):
16631663
self.assertAlmostEqual(data["diff"], 0.0)
16641664
self.assertAlmostEqual(data["diff_pct"], 0.0)
16651665

1666+
def test_diff_flamegraph_elided_values_use_current_interval(self):
1667+
"""Elided geometry and metadata use the same sample units."""
1668+
baseline_frames = [
1669+
MockInterpreterInfo(0, [
1670+
MockThreadInfo(1, [MockFrameInfo("file.py", 10, "old_func")])
1671+
])
1672+
]
1673+
current_frames = [
1674+
MockInterpreterInfo(0, [
1675+
MockThreadInfo(1, [MockFrameInfo("file.py", 20, "new_func")])
1676+
])
1677+
]
1678+
1679+
diff = make_diff_collector_with_mock_baseline(
1680+
[baseline_frames] * 10,
1681+
baseline_interval=1000,
1682+
current_interval=10000,
1683+
)
1684+
diff.collect(current_frames)
1685+
1686+
data = diff._convert_to_flamegraph_format()
1687+
elided = data["stats"]["elided_flamegraph"]
1688+
self.assertAlmostEqual(elided["value"], 1.0)
1689+
self.assertAlmostEqual(elided["self"], 1.0)
1690+
self.assertAlmostEqual(elided["baseline"], 1.0)
1691+
self.assertAlmostEqual(elided["diff"], -1.0)
1692+
16661693
def test_diff_flamegraph_elided_stacks(self):
16671694
"""Paths in baseline but not current produce elided stacks."""
16681695
baseline_frames_1 = [

0 commit comments

Comments
 (0)