Skip to content

Commit 2a2e197

Browse files
Code cleanup
1 parent 1e01766 commit 2a2e197

2 files changed

Lines changed: 26 additions & 18 deletions

File tree

Lib/profiling/sampling/collector.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,24 @@ def _iter_all_frames(self, stack_frames, skip_idle=False):
3838
def _iter_async_frames(self, awaited_info_list):
3939
"""
4040
Iterate over all async frame stacks from awaited info.
41-
Yields one stack per task in LEAF→ROOT order: [task body, task marker, parent body, ..., Program Root]
4241
"""
43-
# Index all tasks by ID
42+
# First, index all tasks by their IDs so we can look up parents easily
4443
all_tasks = {}
4544
for awaited_info in awaited_info_list:
4645
for task_info in awaited_info.awaited_by:
4746
all_tasks[task_info.task_id] = (task_info, awaited_info.thread_id)
4847

49-
cache = {} # Memoize parent chains
48+
# Use a cache for memoizing parent chains so we don't recompute them repeatedly
49+
cache = {}
5050

5151
def build_parent_chain(task_id, parent_id):
52-
"""Build ancestor chain: [await-site frames, grandparent chain..., Program Root]"""
52+
"""
53+
Recursively build the parent chain for a given task by:
54+
- Finding the parent's await-site frames
55+
- Recursing up the parent chain until reaching Program Root
56+
- Add Program Root at the top of the chain
57+
- Cache results along the way to avoid redundant work
58+
"""
5359
if parent_id in cache:
5460
return cache[parent_id]
5561

@@ -72,36 +78,36 @@ def build_parent_chain(task_id, parent_id):
7278
chain = await_frames + build_parent_chain(parent_id, grandparent_id)
7379
else:
7480
# Parent is root or grandparent not tracked
75-
root_frame = FrameInfo(("<thread>", 0, "Program Root"))
81+
root_frame = FrameInfo(("<root>", 0, "<all tasks>"))
7682
chain = await_frames + [root_frame]
7783

7884
cache[parent_id] = chain
7985
return chain
8086

81-
# Yield one stack per task (including parents doing their own work)
82-
for task_id, (task_info, thread_id) in all_tasks.items():
83-
# Collect task's coroutine frames
87+
# Yield one complete stack per task in LEAF→ROOT order
88+
for task_id, (task_info, _) in all_tasks.items():
89+
# Start with the task's own body frames (deepest frames first)
8490
body_frames = [
8591
frame
8692
for coro in (task_info.coroutine_stack or [])
8793
for frame in (coro.call_stack or [])
8894
]
8995

90-
# Build complete stack with parent chain
9196
if task_info.awaited_by and task_info.awaited_by[0].task_name:
92-
# Child task: add synthetic marker to distinguish from parent
97+
# Add synthetic frame for the task itself
9398
task_name = task_info.task_name or f"Task-{task_id}"
9499
synthetic = FrameInfo(("<task>", 0, f"running {task_name}"))
95100

101+
# Append parent chain (await-site frames + parents recursively)
96102
parent_id = task_info.awaited_by[0].task_name
97103
if parent_id in all_tasks:
98104
parent_chain = build_parent_chain(task_id, parent_id)
99-
yield body_frames + [synthetic] + parent_chain, thread_id, 0
105+
yield body_frames + [synthetic] + parent_chain, task_id
100106
else:
101-
# Parent not tracked, treat as root task
102-
root = FrameInfo(("<thread>", 0, "Program Root"))
103-
yield body_frames + [synthetic, root], thread_id, 0
107+
# No tracked parent, just add root marker
108+
root = FrameInfo(("<root>", 0, "<all tasks>"))
109+
yield body_frames + [synthetic, root], task_id
104110
else:
105-
# Root task: no synthetic marker needed, just add Program Root
106-
root = FrameInfo(("<thread>", 0, "Program Root"))
107-
yield body_frames + [root], thread_id, 0
111+
# Root task: no synthetic marker needed, just add root marker
112+
root = FrameInfo(("<root>", 0, "<all tasks>"))
113+
yield body_frames + [root], task_id

Lib/profiling/sampling/stack_collector.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ def __init__(self, *, skip_idle=False):
1616

1717
def collect(self, stack_frames, skip_idle=False):
1818
if stack_frames and hasattr(stack_frames[0], "awaited_by"):
19-
for frames, thread_id, _depth in self._iter_async_frames(stack_frames):
19+
# Async-aware mode: process async task frames
20+
for frames, thread_id in self._iter_async_frames(stack_frames):
2021
if not frames:
2122
continue
2223
self.process_frames(frames, thread_id)
2324
else:
25+
# Sync-only mode
2426
for frames, thread_id in self._iter_all_frames(stack_frames, skip_idle=skip_idle):
2527
if not frames:
2628
continue

0 commit comments

Comments
 (0)