Skip to content

Commit 03ee060

Browse files
authored
gh-138385: Sample all interpreters in the tachyon profiler (#138398)
1 parent 01895d2 commit 03ee060

File tree

7 files changed

+876
-312
lines changed

7 files changed

+876
-312
lines changed

Lib/profiling/sampling/collector.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,11 @@ def collect(self, stack_frames):
99
@abstractmethod
1010
def export(self, filename):
1111
"""Export collected data to a file."""
12+
13+
def _iter_all_frames(self, stack_frames):
14+
"""Iterate over all frame stacks from all interpreters and threads."""
15+
for interpreter_info in stack_frames:
16+
for thread_info in interpreter_info.threads:
17+
frames = thread_info.frame_info
18+
if frames:
19+
yield frames

Lib/profiling/sampling/pstats_collector.py

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,33 @@ def __init__(self, sample_interval_usec):
1515
lambda: collections.defaultdict(int)
1616
)
1717

18-
def collect(self, stack_frames):
19-
for thread_id, frames in stack_frames:
20-
if not frames:
21-
continue
18+
def _process_frames(self, frames):
19+
"""Process a single thread's frame stack."""
20+
if not frames:
21+
return
2222

23-
# Process each frame in the stack to track cumulative calls
24-
for frame in frames:
25-
location = (frame.filename, frame.lineno, frame.funcname)
26-
self.result[location]["cumulative_calls"] += 1
23+
# Process each frame in the stack to track cumulative calls
24+
for frame in frames:
25+
location = (frame.filename, frame.lineno, frame.funcname)
26+
self.result[location]["cumulative_calls"] += 1
2727

28-
# The top frame gets counted as an inline call (directly executing)
29-
top_frame = frames[0]
30-
top_location = (
31-
top_frame.filename,
32-
top_frame.lineno,
33-
top_frame.funcname,
34-
)
28+
# The top frame gets counted as an inline call (directly executing)
29+
top_location = (frames[0].filename, frames[0].lineno, frames[0].funcname)
30+
self.result[top_location]["direct_calls"] += 1
3531

36-
self.result[top_location]["direct_calls"] += 1
32+
# Track caller-callee relationships for call graph
33+
for i in range(1, len(frames)):
34+
callee_frame = frames[i - 1]
35+
caller_frame = frames[i]
3736

38-
# Track caller-callee relationships for call graph
39-
for i in range(1, len(frames)):
40-
callee_frame = frames[i - 1]
41-
caller_frame = frames[i]
37+
callee = (callee_frame.filename, callee_frame.lineno, callee_frame.funcname)
38+
caller = (caller_frame.filename, caller_frame.lineno, caller_frame.funcname)
4239

43-
callee = (
44-
callee_frame.filename,
45-
callee_frame.lineno,
46-
callee_frame.funcname,
47-
)
48-
caller = (
49-
caller_frame.filename,
50-
caller_frame.lineno,
51-
caller_frame.funcname,
52-
)
40+
self.callers[callee][caller] += 1
5341

54-
self.callers[callee][caller] += 1
42+
def collect(self, stack_frames):
43+
for frames in self._iter_all_frames(stack_frames):
44+
self._process_frames(frames)
5545

5646
def export(self, filename):
5747
self.create_stats()

Lib/profiling/sampling/stack_collector.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,22 @@ def __init__(self):
99
self.call_trees = []
1010
self.function_samples = collections.defaultdict(int)
1111

12+
def _process_frames(self, frames):
13+
"""Process a single thread's frame stack."""
14+
if not frames:
15+
return
16+
17+
# Store the complete call stack (reverse order - root first)
18+
call_tree = list(reversed(frames))
19+
self.call_trees.append(call_tree)
20+
21+
# Count samples per function
22+
for frame in frames:
23+
self.function_samples[frame] += 1
24+
1225
def collect(self, stack_frames):
13-
for thread_id, frames in stack_frames:
14-
if frames:
15-
# Store the complete call stack (reverse order - root first)
16-
call_tree = list(reversed(frames))
17-
self.call_trees.append(call_tree)
18-
19-
# Count samples per function
20-
for frame in frames:
21-
self.function_samples[frame] += 1
26+
for frames in self._iter_all_frames(stack_frames):
27+
self._process_frames(frames)
2228

2329

2430
class CollapsedStackCollector(StackTraceCollector):

0 commit comments

Comments
 (0)