summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2025-06-15 23:34:15 -0400
committerbd <bdunahu@operationnull.com>2025-06-15 23:34:15 -0400
commit1a9808431219db676b4c7482992707584c3071e2 (patch)
treeaabeb6ff3d030c11c72188422d38ed1c1ac40e40
parent8844dceadcdeebf67d07656bf45d3ddada3e2b5b (diff)
Rename to Aergia
-rw-r--r--aergia.py (renamed from mini_scalene.py)92
1 files changed, 33 insertions, 59 deletions
diff --git a/mini_scalene.py b/aergia.py
index f7a8ca9..534880f 100644
--- a/mini_scalene.py
+++ b/aergia.py
@@ -1,18 +1,11 @@
-import selectors
-
import sys
import argparse
import threading
import traceback
-import atexit
import signal
import asyncio
import time
-from typing import (
- Any,
- Callable,
- cast,
-)
+from typing import cast
from types import FrameType
from collections import defaultdict
import replacement_epoll_selector
@@ -29,6 +22,7 @@ the_globals = {
'__cached__': None,
}
+
def parse_arguments():
'''Parse CLI args'''
parser = argparse.ArgumentParser()
@@ -45,12 +39,12 @@ def parse_arguments():
return parser.parse_args()
-class MiniScalene(object):
+class Aergia(object):
'''A stripped-down version of SCALENE which tallies active lines during
execution.'''
# a key-value pair where keys represent frame metadata (see
- # MiniScalene.frame_to_string) and values represent number of times
+ # Aergia.frame_to_string) and values represent number of times
# sampled.
cpu_samples = defaultdict(lambda: 0)
cpu_samples_c = defaultdict(lambda: 0)
@@ -72,7 +66,7 @@ class MiniScalene(object):
signal.setitimer(signal.ITIMER_PROF,
self.signal_interval,
self.signal_interval)
- MiniScalene.last_signal_time = MiniScalene.gettime()
+ Aergia.last_signal_time = Aergia.gettime()
@staticmethod
def gettime():
@@ -81,29 +75,29 @@ class MiniScalene(object):
@staticmethod
def start(profile_async):
- MiniScalene.profile_async = profile_async
+ Aergia.profile_async = profile_async
@staticmethod
def stop():
'''Turn off profiling signals'''
- MiniScalene.disable_signals()
- MiniScalene.exit_handler()
+ Aergia.disable_signals()
+ Aergia.exit_handler()
@staticmethod
def exit_handler():
'''Pretty-print profiling information.'''
# If we've collected any samples, dump them.
print("CPU usage (Python):")
- if MiniScalene.total_cpu_samples > 0:
- for key in MiniScalene.sort_samples(MiniScalene.cpu_samples):
+ if Aergia.total_cpu_samples > 0:
+ for key in Aergia.sort_samples(Aergia.cpu_samples):
print(f"{key} : "
- f"{MiniScalene.cpu_samples[key] * 100 / MiniScalene.total_cpu_samples:.3f} % "
- f"({MiniScalene.cpu_samples[key]:.1f} total samples)")
+ f"{Aergia.cpu_samples[key] * 100 / Aergia.total_cpu_samples:.3f} % "
+ f"({Aergia.cpu_samples[key]:.1f} total samples)")
print("CPU usage (Native):")
- for key in MiniScalene.sort_samples(MiniScalene.cpu_samples_c):
+ for key in Aergia.sort_samples(Aergia.cpu_samples_c):
print(f"{key} : "
- f"{MiniScalene.cpu_samples_c[key] * 100 / MiniScalene.total_cpu_samples:.3f} % "
- f"({MiniScalene.cpu_samples_c[key]:.1f} total samples)")
+ f"{Aergia.cpu_samples_c[key] * 100 / Aergia.total_cpu_samples:.3f} % "
+ f"({Aergia.cpu_samples_c[key]:.1f} total samples)")
else:
print("(did not run long enough to profile)")
@@ -115,30 +109,30 @@ class MiniScalene(object):
@staticmethod
def cpu_signal_handler(sig, frame):
- elapsed_since_last_signal = MiniScalene.gettime() - \
- MiniScalene.last_signal_time
+ elapsed_since_last_signal = Aergia.gettime() - \
+ Aergia.last_signal_time
c_time_norm = (elapsed_since_last_signal -
- MiniScalene.signal_interval) / \
- MiniScalene.signal_interval
+ Aergia.signal_interval) / \
+ Aergia.signal_interval
- keys = MiniScalene.compute_frames_to_record(frame)
+ keys = Aergia.compute_frames_to_record(frame)
for key in keys:
- MiniScalene.cpu_samples[MiniScalene.frame_to_string(key)] += 1
- MiniScalene.cpu_samples_c[MiniScalene.frame_to_string(
+ Aergia.cpu_samples[Aergia.frame_to_string(key)] += 1
+ Aergia.cpu_samples_c[Aergia.frame_to_string(
key)] += c_time_norm
- MiniScalene.total_cpu_samples += elapsed_since_last_signal / \
- MiniScalene.signal_interval
- MiniScalene.last_signal_time = MiniScalene.gettime()
+ Aergia.total_cpu_samples += elapsed_since_last_signal / \
+ Aergia.signal_interval
+ Aergia.last_signal_time = Aergia.gettime()
@staticmethod
def compute_frames_to_record(this_frame):
- '''Collects all stack frames that Scalene actually processes.'''
+ '''Collects all stack frames that Aergia actually processes.'''
frames = [this_frame]
frames += [sys._current_frames().get(t.ident, None)
for t in threading.enumerate()]
- frames += MiniScalene.get_async_frames()
+ frames += Aergia.get_async_frames()
- frames = MiniScalene.filter_duplicated_frames(frames)
+ frames = Aergia.filter_duplicated_frames(frames)
# Process all the frames to remove ones we aren't going to track.
new_frames = []
for frame in frames:
@@ -151,7 +145,7 @@ class MiniScalene(object):
# to look back into the outer frame in order to check
# the co_filename.
fname = frame.f_back.f_code.co_filename
- while not MiniScalene.should_trace(fname):
+ while not Aergia.should_trace(fname):
# Walk the stack backwards until we hit a frame that
# IS one we should trace (if there is one). i.e., if
# it's in the code being profiled, and it is just
@@ -179,7 +173,7 @@ class MiniScalene(object):
@staticmethod
def get_async_frames():
'''Obtains the stack frames of all currently executing tasks.'''
- if MiniScalene.is_event_loop_running() and MiniScalene.profile_async:
+ if Aergia.is_event_loop_running() and Aergia.profile_async:
return [task.get_coro().cr_frame for task in asyncio.all_tasks()]
return []
@@ -191,7 +185,7 @@ class MiniScalene(object):
return False
if filename[0] == '<':
return False
- if 'mini_scalene.py' in filename:
+ if 'aergia.py' in filename:
return False
return True
@@ -209,26 +203,6 @@ class MiniScalene(object):
reverse=True)}
@staticmethod
- def shim(func: Callable[[Any], Any]) -> Any:
- """Provide a decorator that calls the wrapped function with the
- Scalene variant.
-
- Wrapped function must be of type (s: Scalene) -> Any.
-
- This decorator allows for marking a function in a separate
- file as a drop-in replacement for an existing library
- function. The intention is for these functions to replace a
- function that indefinitely blocks (which interferes with
- Scalene) with a function that awakens periodically to allow
- for signals to be delivered.
-
- """
- func(MiniScalene)
- # Returns the function itself to the calling file for the sake
- # of not displaying unusual errors if someone attempts to call
- # it
-
- @staticmethod
def filter_duplicated_frames(frames) -> bool:
s = set()
dup = []
@@ -254,9 +228,9 @@ def main():
try:
with open(args.script, 'rb') as fp:
code = compile(fp.read(), args.script, "exec")
- MiniScalene().start(args.async_off)
+ Aergia().start(args.async_off)
exec(code, the_globals)
- MiniScalene().stop()
+ Aergia().stop()
except Exception:
traceback.print_exc()