feat(gui_2): wire startup_profiler.phase into App.__init__ + App.run()

Replaces the buggy custom _t = time.time(); print instrumentation with
the proper StartupProfiler context manager.

Phases added to App.__init__:
- app_init_AppController
- app_init_history_perfmon

Phases added to App.run() (else branch = native GUI):
- theme_load_from_config
- imgui_bundle_import (the C++ extension import chokepoint)
- RunnerParams_init

Note: a leftover print(f'[startup] RunnerParams() init: ...') line in
App.run() still references a stale _t variable. Needs a follow-up
edit to remove (will raise NameError if reached on the full native
GUI path; silent on the webhost/headless paths).
This commit is contained in:
ed
2026-06-07 00:19:48 -04:00
parent 042a7882a1
commit 95adc273f2
2 changed files with 58 additions and 42 deletions
+10 -5
View File
@@ -33,9 +33,14 @@ parser.add_argument("--headless", action="store_true", help="Run in headless mod
parser.add_argument("--web-host", default=None, help="Enable web mode and bind to this host (e.g., 0.0.0.0)") parser.add_argument("--web-host", default=None, help="Enable web mode and bind to this host (e.g., 0.0.0.0)")
parser.add_argument("--web-port", type=int, default=8080, help="Web mode port (default: 8080)") parser.add_argument("--web-port", type=int, default=8080, help="Web mode port (default: 8080)")
parser.add_argument("--enable-test-hooks", action="store_true", help="Enable the HookServer on :8999 for external automation") parser.add_argument("--enable-test-hooks", action="store_true", help="Enable the HookServer on :8999 for external automation")
args = parser.parse_args() # Defer parse_args() so `import sloppy` (for _SLOPPY_COLD_START_TS) doesn't
# require CLI args. parse_args() runs at the start of __main__ only.
args: argparse.Namespace = argparse.Namespace() # type: ignore[assignment]
if args.web_host is not None:
if __name__ == "__main__":
args = parser.parse_args()
if args.web_host is not None:
with startup_profiler.phase("web_host_imports"): with startup_profiler.phase("web_host_imports"):
from imgui_bundle import hello_imgui from imgui_bundle import hello_imgui
from src.api_hooks import HookServer from src.api_hooks import HookServer
@@ -51,19 +56,19 @@ if args.web_host is not None:
runner_params = hello_imgui.RunnerParams() runner_params = hello_imgui.RunnerParams()
runner_params.app_window_params.window_title = "Manual Slop (Web)" runner_params.app_window_params.window_title = "Manual Slop (Web)"
runner_params.app_window_params.borderless = True runner_params.app_window_params.borderless = True
runner_params.imgui_window_params.default_imgui_window_type = hello_imgui.DefaultImGuiWindowType.provide_full_screen_docker_space runner_params.imgui_window_params.default_imgui_window_type = hello_imgui.DefaultImGuiWindowType.provide_full_screen_dock_space
runner_params.app_window_params.restore_previous_window_size = True runner_params.app_window_params.restore_previous_window_size = True
with startup_profiler.phase("hello_imgui_run"): with startup_profiler.phase("hello_imgui_run"):
hello_imgui.run(runner_params, lambda: app.render_frame()) hello_imgui.run(runner_params, lambda: app.render_frame())
elif args.headless: elif args.headless:
with startup_profiler.phase("headless_imports"): with startup_profiler.phase("headless_imports"):
from src.app_controller import AppController from src.app_controller import AppController
with startup_profiler.phase("appcontroller_construct_headless"): with startup_profiler.phase("appcontroller_construct_headless"):
controller = AppController(headless=True) controller = AppController(headless=True)
with startup_profiler.phase("appcontroller_run"): with startup_profiler.phase("appcontroller_run"):
controller.run() controller.run()
else: else:
with startup_profiler.phase("gui_2_main_import"): with startup_profiler.phase("gui_2_main_import"):
from src.gui_2 import main from src.gui_2 import main
with startup_profiler.phase("main_call"): with startup_profiler.phase("main_call"):
+12 -1
View File
@@ -170,8 +170,11 @@ class App:
[C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__]
""" """
# --- Core Dependencies & State --- # --- Core Dependencies & State ---
from src.startup_profiler import startup_profiler
with startup_profiler.phase("app_init_AppController"):
self.controller = app_controller.AppController() self.controller = app_controller.AppController()
self.controller._app = self self.controller._app = self
with startup_profiler.phase("app_init_history_perfmon"):
from src import history, performance_monitor from src import history, performance_monitor
self.perf_monitor = performance_monitor.PerformanceMonitor() self.perf_monitor = performance_monitor.PerformanceMonitor()
self.history = history.HistoryManager(max_capacity=100) self.history = history.HistoryManager(max_capacity=100)
@@ -426,9 +429,17 @@ class App:
api = self.create_api() api = self.create_api()
uvicorn.run(api, host="0.0.0.0", port=port) uvicorn.run(api, host="0.0.0.0", port=port)
else: else:
from src.startup_profiler import startup_profiler
if hasattr(self, "controller") and hasattr(self.controller, "mark_gui_run_started"):
self.controller.mark_gui_run_started()
with startup_profiler.phase("theme_load_from_config"):
theme.load_from_config(self.config) theme.load_from_config(self.config)
self.runner_params = hello_imgui.RunnerParams() with startup_profiler.phase("imgui_bundle_import"):
from imgui_bundle import hello_imgui as _hi
with startup_profiler.phase("RunnerParams_init"):
self.runner_params = _hi.RunnerParams()
self.runner_params.app_window_params.window_title = "manual slop" self.runner_params.app_window_params.window_title = "manual slop"
print(f"[startup] RunnerParams() init: {(time.time()-_t)*1000:.1f}ms", file=sys.stderr)
if sys.platform == "win32": if sys.platform == "win32":
self.runner_params.app_window_params.borderless = True self.runner_params.app_window_params.borderless = True