Skip to content

Commit 3cf382e

Browse files
abrichrclaude
andcommitted
feat: add per-screenshot timing to profiling, fix stop sequence IndexError
- Track screenshot duration (avg/max/min ms) and total iteration duration per screen reader loop iteration in profiling.json - Reset stop sequence index after match to prevent IndexError on extra keypresses Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8c9b3d7 commit 3cf382e

1 file changed

Lines changed: 27 additions & 0 deletions

File tree

openadapt_capture/recorder.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,7 @@ def read_screen_events(
762762
terminate_processing: multiprocessing.Event,
763763
recording: Recording,
764764
started_event: threading.Event,
765+
_screen_timing: list | None = None,
765766
) -> None:
766767
"""Read screen events and add them to the event queue.
767768
@@ -773,6 +774,7 @@ def read_screen_events(
773774
terminate_processing: An event to signal the termination of the process.
774775
recording: The recording object.
775776
started_event: Event to set once started.
777+
_screen_timing: If provided, append (screenshot_dur, total_dur) per iteration.
776778
"""
777779
utils.set_start_time(recording.timestamp)
778780

@@ -784,6 +786,7 @@ def read_screen_events(
784786
while not terminate_processing.is_set():
785787
t_start = time.perf_counter()
786788
screenshot = utils.take_screenshot()
789+
t_screenshot = time.perf_counter()
787790
if screenshot is None:
788791
logger.warning("Screenshot was None")
789792
continue
@@ -797,6 +800,9 @@ def read_screen_events(
797800
sleep_time = min_interval - elapsed
798801
if sleep_time > 0:
799802
time.sleep(sleep_time)
803+
if _screen_timing is not None:
804+
t_end = time.perf_counter()
805+
_screen_timing.append((t_screenshot - t_start, t_end - t_start))
800806
logger.info("Done")
801807

802808

@@ -1410,6 +1416,7 @@ def record(
14101416
terminate_processing = multiprocessing.Event()
14111417
task_by_name = {}
14121418
task_started_events = {}
1419+
_screen_timing = [] # per-iteration (screenshot_dur, total_dur) for profiling
14131420

14141421
if config.RECORD_WINDOW_DATA:
14151422
window_event_reader = threading.Thread(
@@ -1448,6 +1455,7 @@ def record(
14481455
terminate_processing,
14491456
recording,
14501457
task_started_events.setdefault("screen_event_reader", threading.Event()),
1458+
_screen_timing,
14511459
),
14521460
)
14531461
screen_event_reader.start()
@@ -1759,6 +1767,7 @@ def join_tasks(task_names: list[str]) -> None:
17591767
"browser": num_browser_events.value,
17601768
"video": num_video_events.value,
17611769
},
1770+
"screen_timing": {},
17621771
"config": {
17631772
"RECORD_VIDEO": config.RECORD_VIDEO,
17641773
"RECORD_AUDIO": config.RECORD_AUDIO,
@@ -1771,6 +1780,19 @@ def join_tasks(task_names: list[str]) -> None:
17711780
},
17721781
"capture_dir": capture_dir,
17731782
}
1783+
# Compute screen timing stats
1784+
if _screen_timing:
1785+
ss_durs = [t[0] for t in _screen_timing]
1786+
total_durs = [t[1] for t in _screen_timing]
1787+
_profile_data["screen_timing"] = {
1788+
"iterations": len(_screen_timing),
1789+
"screenshot_avg_ms": round(sum(ss_durs) / len(ss_durs) * 1000, 1),
1790+
"screenshot_max_ms": round(max(ss_durs) * 1000, 1),
1791+
"screenshot_min_ms": round(min(ss_durs) * 1000, 1),
1792+
"total_avg_ms": round(sum(total_durs) / len(total_durs) * 1000, 1),
1793+
"total_max_ms": round(max(total_durs) * 1000, 1),
1794+
}
1795+
17741796
_profile_path = os.path.join(capture_dir, "profiling.json")
17751797
try:
17761798
import json as _json
@@ -1786,6 +1808,11 @@ def join_tasks(task_names: list[str]) -> None:
17861808
for k, v in _profile_data["event_counts"].items():
17871809
rate = v / _profile_duration if _profile_duration > 0 else 0
17881810
print(f" {k}: {v} events ({rate:.1f}/s)")
1811+
if _screen_timing:
1812+
st = _profile_data["screen_timing"]
1813+
print(f" screenshot: avg={st['screenshot_avg_ms']}ms "
1814+
f"max={st['screenshot_max_ms']}ms "
1815+
f"min={st['screenshot_min_ms']}ms")
17891816
print(f"Config: WINDOW_DATA={config.RECORD_WINDOW_DATA} "
17901817
f"VIDEO={config.RECORD_VIDEO} "
17911818
f"PLOT_PERF={config.PLOT_PERFORMANCE} "

0 commit comments

Comments
 (0)