Speed up plugin startup port checks#285
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
Speeds up Godot AI plugin startup by reducing expensive external port checks and adding opt-in startup timing traces for diagnosing remaining startup latency.
Changes:
- Add opt-in startup timing tracing (env
GODOT_AI_STARTUP_TRACEor EditorSettinggodot_ai/log_startup_timing) with per-tool counters/phases. - Avoid
netstat/lsofon the “port is free” path by attempting a loopback bind first, and prefernetstatover PowerShell for Windows PID lookup. - Cache Windows
netsh interface ipv4 show excludedportrangeoutput briefly (TTL) and add tests for the cache.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
test_project/tests/test_windows_port_reservation.gd |
Adds unit tests covering the new netsh excluded-port output cache behavior (TTL hit/expire/clear). |
plugin/addons/godot_ai/utils/windows_port_reservation.gd |
Implements a short-lived cache for netsh output and tracks netsh query count for startup tracing. |
plugin/addons/godot_ai/plugin.gd |
Adds startup trace plumbing, switches free-port detection to “try bind first”, and makes Windows PID lookup netstat-first with PowerShell fallback. |
plugin/addons/godot_ai/client_configurator.gd |
Registers a new EditorSetting and env var handling for enabling startup timing traces. |
Comments suppressed due to low confidence (1)
plugin/addons/godot_ai/plugin.gd:154
_startup_trace_begin()is invoked before the headless-disable early return, so when the plugin is disabled for headless launches a trace can print “begin” without ever printing a matching “done”. Consider moving_startup_trace_begin()to after the_mcp_disabled_for_headless_launch()guard, or calling_startup_trace_finish("headless_disabled")just before returning.
func _enter_tree() -> void:
_startup_trace_begin()
## `_process` is only used by the adoption-confirmation watcher; keep
## it off until `_watch_for_adoption_confirmation` arms it, so the
## plugin has zero per-frame cost in the common case.
set_process(false)
if _mcp_disabled_for_headless_launch():
_headless_disabled = true
print("MCP | plugin disabled in headless mode")
return
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Further startup-speedup targets (post-#285 review)With this PR landed, the free-port path is fast and the netstat/PowerShell scrapes are gated, so the remaining ~80%-loaded ditch is most likely main-thread work in the dock's first paint, not the port checks. Ranked by likely impact:
Recommendation: turn on Generated by Claude Code |
Startup trace follow-upRan the requested startup experiments on this PR branch ( 1. Default editor settings / default portsThis did not exercise the free-port path. Port 8000 was occupied by an existing Python listener ( Takeaway: the biggest measured stall here is review item #3. The synchronous occupied-port/status-probe path can still cost seconds when the port is held by an unverified server. 2. Isolated fresh editor settings / alternate free portsI ran with isolated Takeaway: for the normal free-port spawned path, the PR is doing what we want: no PowerShell/netstat/lsof/status-probe work, and plugin-side startup is ~250ms. The largest remaining plugin phase in this trace is dock attach/build (~187ms), not port discovery. 3.
|
Summary
GODOT_AI_STARTUP_TRACEor thegodot_ai/log_startup_timingeditor settingnetshexcluded-port outputVerification
git diff --checkGodot_v4.6.2-stable_win64_console.exe --headless --path test_project --import(exited 0; sandbox could not save user-level Godot editor settings)main