feat(effects): add performance monitoring to effect pipeline

- Add PerformanceMonitor to collect per-effect timings
- Track effect duration (ms), buffer chars in/out per frame
- Store last 60 frames in ring buffer
- Add /effects stats NTFY command to view performance data
- Add tests for performance monitoring system
This commit is contained in:
2026-03-15 17:24:38 -07:00
parent 291e96d11e
commit f5a086154a
5 changed files with 210 additions and 1 deletions

View File

@@ -1,3 +1,4 @@
from engine.effects.performance import get_monitor
from engine.effects.registry import get_registry
@@ -16,6 +17,7 @@ def handle_effects_command(cmd: str) -> str:
/effects <name> off - disable an effect
/effects <name> intensity <0.0-1.0> - set intensity
/effects reorder <name1>,<name2>,... - reorder pipeline
/effects stats - show performance statistics
"""
parts = cmd.strip().split()
if not parts or parts[0] != "/effects":
@@ -34,6 +36,9 @@ def handle_effects_command(cmd: str) -> str:
result.append(f"Order: {chain.get_order()}")
return "\n".join(result)
if parts[1] == "stats":
return _format_stats()
if len(parts) < 3:
return "Usage: /effects <name> on|off|intensity <value>"
@@ -72,6 +77,30 @@ def handle_effects_command(cmd: str) -> str:
return f"Unknown action: {action}"
def _format_stats() -> str:
monitor = get_monitor()
stats = monitor.get_stats()
if "error" in stats:
return stats["error"]
lines = ["Performance Stats:"]
pipeline = stats["pipeline"]
lines.append(
f" Pipeline: avg={pipeline['avg_ms']:.2f}ms min={pipeline['min_ms']:.2f}ms max={pipeline['max_ms']:.2f}ms (over {stats['frame_count']} frames)"
)
if stats["effects"]:
lines.append(" Per-effect (avg ms):")
for name, effect_stats in stats["effects"].items():
lines.append(
f" {name}: avg={effect_stats['avg_ms']:.2f}ms min={effect_stats['min_ms']:.2f}ms max={effect_stats['max_ms']:.2f}ms"
)
return "\n".join(lines)
def show_effects_menu() -> str:
"""Generate effects menu text for display."""
registry = get_registry()