From 5d7f40a890a1a1dd6dc7dc2982308932ba86cc42 Mon Sep 17 00:00:00 2001 From: bd Date: Mon, 9 Jun 2025 19:16:37 -0400 Subject: Add naive async profiling functionality and proof of concept program --- mini-scalene.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'mini-scalene.py') diff --git a/mini-scalene.py b/mini-scalene.py index 2fa5b59..01a8de2 100644 --- a/mini-scalene.py +++ b/mini-scalene.py @@ -4,6 +4,8 @@ import traceback import runpy import atexit import signal +import asyncio +import inspect from typing import cast from types import FrameType from collections import defaultdict @@ -55,6 +57,7 @@ class mini_scalene: frames = [this_frame] frames += [sys._current_frames().get(t.ident, None) for t in threading.enumerate()] + frames += mini_scalene.get_async_frames() # Process all the frames to remove ones we aren't going to track. new_frames = [] for frame in frames: @@ -90,6 +93,12 @@ class mini_scalene: filename = co.co_filename return filename + '\t' + func_name + '\t' + str(line_no) + @staticmethod + def get_async_frames(): + if mini_scalene.is_event_loop_running(): + return [task.get_coro().cr_frame for task in asyncio.all_tasks()] + return [] + @staticmethod def should_trace(filename): # We're assuming Guix System. That makes it easy. @@ -103,10 +112,14 @@ class mini_scalene: return False return True + @staticmethod + def is_event_loop_running() -> bool: + return asyncio.get_event_loop_policy()._local._loop is not None + + def main(): - assert len( - sys.argv) >= 2, "(Usage): python3 mini-scalene.py file.py {args ...}" + assert len(sys.argv) >= 2, "(Usage): python3 mini-scalene.py file.py {args ...}" script = sys.argv[1] mini_scalene().start() -- cgit v1.2.3