perf(gateway): 10x faster cold project grouping (3.3s → 0.3s) (#82472)

* perf(gateway): stop spawning git for paths that cannot answer

The project tree probes every distinct session cwd, and on a long-lived
history most of those directories are deleted worktrees — `git -C` there
can only fail, at the price of a fork each. Stat first.

The second elision is `common_repo_root`: only repos have a common dir,
and the parallel warm never covers that probe because `resolve()` reaches
it only for cwds that already resolved. Every non-repo cwd was therefore
paying a serial `git` spawn on the discovery pass.

* perf(gateway): quit reading system prompts the project tree discards

`_project_tree_row` keeps about eighteen fields and drops the rest, but
the query behind it selected `s.*` plus the resolved system prompt — 37MB
of blob per build on my session history, read out of the B-tree and then
thrown away.

* perf(gateway): warm every path the project tree will resolve

The warm covered session cwds, but build_tree also resolves each declared
project folder and each discovered repo root. Those were the last probes
running one directory at a time while the sidebar showed a skeleton.
This commit is contained in:
brooklyn! 2026-08-09 07:02:37 -05:00 committed by GitHub
commit 2446c8bb67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 82 additions and 1 deletions

View File

@ -146,6 +146,65 @@ def test_warm_roots_probes_in_parallel_and_fills_the_cache(monkeypatch):
assert live["calls"] == before
def test_missing_directory_costs_no_subprocess(monkeypatch):
# Deleted worktrees dominate a long session history's cwds, and `git -C` on
# one can only fail — so it must never reach the fork.
from tui_gateway import git_probe
def boom(*_a, **_kw):
raise AssertionError("spawned git for a directory that does not exist")
monkeypatch.setattr(git_probe, "bounded_git_probe", boom)
assert git_probe.run_git("/gone/worktree", "rev-parse", "--show-toplevel") == ""
def test_non_repo_cwd_is_not_probed_for_a_common_dir(monkeypatch, tmp_path):
# `warm_roots` only reaches `common_repo_root` for cwds that ARE repos, so a
# common-dir probe here is one the warm can't absorb: it runs serially on
# the discovery pass, once per non-repo cwd.
from tui_gateway import git_probe
git_probe.invalidate()
asked = []
def probe(cwd, *args):
asked.append(args[-1])
return "" # not a repo, whatever we ask
monkeypatch.setattr(git_probe, "run_git", probe)
assert git_probe.common_repo_root(str(tmp_path)) == ""
assert asked == ["--show-toplevel"]
def test_tree_build_warms_every_path_it_will_resolve(monkeypatch, tmp_path):
# build_tree resolves declared project folders and discovered repo roots as
# well as session cwds. Anything left out of the warm is probed one
# directory at a time while the sidebar shows a skeleton.
from tui_gateway import git_probe
repo = tmp_path / "repo"
(repo / ".git").mkdir(parents=True)
_call("projects.create", {"name": "Repo", "folders": [str(repo)]})
warmed: list[str] = []
real_warm = git_probe.warm_roots
def recording_warm(cwds, **kw):
paths = list(cwds)
warmed.extend(paths)
return real_warm(paths, **kw)
monkeypatch.setattr(git_probe, "warm_roots", recording_warm)
server._build_project_tree(
server._get_db(), preview_limit=3, hydrate=False, session_limit=5, include_discovered=True
)
assert str(repo) in warmed
def test_create_list_roundtrip(tmp_path):
created = _call("projects.create", {"name": "Demo", "folders": [str(tmp_path)], "use": True})
assert created["project"]["slug"] == "demo"

View File

@ -50,7 +50,11 @@ def run_git(cwd: str, *args: str) -> str:
session readiness when a killed git left a suspended descendant holding the
pipe handles (issue #68609).
"""
if not cwd:
if not cwd or not os.path.isdir(cwd):
# `git -C` on a directory that no longer exists can only fail, and it
# fails at the price of a fork. Deleted worktrees dominate the cwds a
# long-lived session history hands us, so the stat pays for itself many
# times over on every project-tree build.
return ""
return bounded_git_probe(["git", "-C", cwd, *args], timeout=_GIT_TIMEOUT)
@ -153,6 +157,13 @@ def common_repo_root(cwd: str) -> str:
if not cwd:
return ""
# No work tree, nothing to fold. Reading the (warmed, negative-cached)
# toplevel first spares every non-repo cwd a second `git` spawn — one the
# parallel warm can never absorb, since `resolve()` only reaches here for
# cwds that ARE repos.
if not repo_root(cwd):
return ""
def _probe() -> str:
gitdir = run_git(cwd, "rev-parse", "--path-format=absolute", "--git-common-dir")
if gitdir:

View File

@ -11772,6 +11772,10 @@ def _project_tree_inputs(
include_children=False,
exclude_sources=_PROJECT_TREE_EXCLUDED_SOURCES,
include_archived=False,
# `_project_tree_row` keeps ~18 fields and drops the rest, so selecting
# the system-prompt blob only to discard it costs tens of MB of B-tree
# reads per build on a long-lived database.
compact_rows=True,
)
sessions = [_project_tree_row(r) for r in rows]
# Parallel-warm the git cache so build_tree's resolver reads it instead of
@ -11838,6 +11842,13 @@ def _build_project_tree(
sessions, projects, discovered, active_id = _project_tree_inputs(
db, session_limit, include_discovered=include_discovered
)
# build_tree resolves every declared project folder and every discovered
# repo root too, and those paths are not session cwds — without this they
# are the one part of the build still probing git one directory at a time.
git_probe.warm_roots(
[str(f.get("path") or "") for p in projects for f in (p.get("folders") or [])]
+ [str(r.get("root") or "") for r in discovered]
)
tree = project_tree.build_tree(
projects,
sessions,