Skip to content

Commit e4e80a0

Browse files
committed
pythongh-154032: Scale elided flamegraph values
1 parent 9cd487b commit e4e80a0

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
@@ -653,6 +653,7 @@ def _build_elided_flamegraph(self, baseline_stats, scale):
653653
if not self._extract_elided_nodes(baseline_data, path=()):
654654
return None
655655

656+
self._scale_flamegraph_values(baseline_data, scale)
656657
self._add_elided_metadata(baseline_data, baseline_stats, scale, path=())
657658

658659
# Merge only profiling metadata, not thread-level stats
@@ -666,6 +667,13 @@ def _build_elided_flamegraph(self, baseline_stats, scale):
666667

667668
return baseline_data
668669

670+
def _scale_flamegraph_values(self, node, scale):
671+
"""Express flamegraph values in units of the current sample interval."""
672+
node["value"] = node.get("value", 0) * scale
673+
node["self"] = node.get("self", 0) * scale
674+
for child in node.get("children", ()):
675+
self._scale_flamegraph_values(child, scale)
676+
669677
def _extract_elided_nodes(self, node, path):
670678
"""Remove non-elided nodes and recalculate values bottom-up."""
671679
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
@@ -1579,6 +1579,33 @@ def test_diff_flamegraph_scale_factor_uses_sample_intervals(self):
15791579
self.assertAlmostEqual(data["diff"], 0.0)
15801580
self.assertAlmostEqual(data["diff_pct"], 0.0)
15811581

1582+
def test_diff_flamegraph_elided_values_use_current_interval(self):
1583+
"""Elided geometry and metadata use the same sample units."""
1584+
baseline_frames = [
1585+
MockInterpreterInfo(0, [
1586+
MockThreadInfo(1, [MockFrameInfo("file.py", 10, "old_func")])
1587+
])
1588+
]
1589+
current_frames = [
1590+
MockInterpreterInfo(0, [
1591+
MockThreadInfo(1, [MockFrameInfo("file.py", 20, "new_func")])
1592+
])
1593+
]
1594+
1595+
diff = make_diff_collector_with_mock_baseline(
1596+
[baseline_frames] * 10,
1597+
baseline_interval=1000,
1598+
current_interval=10000,
1599+
)
1600+
diff.collect(current_frames)
1601+
1602+
data = diff._convert_to_flamegraph_format()
1603+
elided = data["stats"]["elided_flamegraph"]
1604+
self.assertAlmostEqual(elided["value"], 1.0)
1605+
self.assertAlmostEqual(elided["self"], 1.0)
1606+
self.assertAlmostEqual(elided["baseline"], 1.0)
1607+
self.assertAlmostEqual(elided["diff"], -1.0)
1608+
15821609
def test_diff_flamegraph_elided_stacks(self):
15831610
"""Paths in baseline but not current produce elided stacks."""
15841611
baseline_frames_1 = [

0 commit comments

Comments
 (0)