mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-14 16:09:26 +00:00
_source_key and _resolve_cached key their lru_cache on the path and the
cwd, and call os.getcwd() on every lookup, hit or miss. On a 900-file
repo an extract makes about 215k of those calls. os.getcwd() is a
syscall that costs 30 to 40us on macOS, so building the key cost more
than the resolution the memo saved.
An absolute path resolves the same from any cwd, so it now keys with an
empty cwd. A relative path still keys on the cwd, so a chdir still misses
the cache. Path.is_absolute() applies host rules, which is what local
resolution needs: a driveless path on Windows depends on the drive.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 2228f80804)
105 lines
3.8 KiB
Python
105 lines
3.8 KiB
Python
"""_source_key memoization: same answers, a fraction of the syscalls (#perf).
|
|
|
|
``_disambiguate_colliding_node_ids`` computes a source key once per node, per
|
|
edge endpoint and per raw_call — tens of thousands of calls for a few hundred
|
|
distinct ``source_file`` strings — and each uncached call walked the path
|
|
through ``Path.resolve()``'s syscall chain. On a 364-file corpus the pass
|
|
spent 15s (34% of a sequential extract) re-resolving identical strings.
|
|
"""
|
|
|
|
import os
|
|
|
|
import pytest
|
|
|
|
from graphify.extractors.resolution import _source_key
|
|
|
|
try:
|
|
from graphify.extractors.resolution import _cached_source_key
|
|
except ImportError: # pre-fix tree: the memoized helper does not exist
|
|
_cached_source_key = None
|
|
|
|
needs_cache = pytest.mark.skipif(
|
|
_cached_source_key is None, reason="memoized helper not present"
|
|
)
|
|
|
|
|
|
def _reference_source_key(source_file, root):
|
|
"""The pre-memoization implementation, verbatim."""
|
|
from pathlib import Path
|
|
|
|
if not source_file:
|
|
return ""
|
|
source_path = Path(source_file)
|
|
try:
|
|
return str(source_path.resolve().relative_to(root))
|
|
except Exception:
|
|
return str(source_path)
|
|
|
|
|
|
def test_matches_unmemoized_semantics(tmp_path, monkeypatch):
|
|
monkeypatch.chdir(tmp_path)
|
|
(tmp_path / "pkg").mkdir()
|
|
(tmp_path / "pkg" / "mod.py").write_text("x = 1\n", encoding="utf-8")
|
|
outside = tmp_path.parent
|
|
|
|
cases = [
|
|
("pkg/mod.py", tmp_path), # relative, in-root
|
|
(str(tmp_path / "pkg" / "mod.py"), tmp_path), # absolute, in-root
|
|
(str(outside), tmp_path), # out-of-root -> fallback
|
|
("pkg/ghost.py", tmp_path), # nonexistent
|
|
("", tmp_path), # empty
|
|
]
|
|
for source_file, root in cases:
|
|
assert _source_key(source_file, root) == _reference_source_key(
|
|
source_file, root
|
|
), (source_file, root)
|
|
|
|
|
|
@needs_cache
|
|
def test_resolution_happens_once_per_distinct_path(tmp_path, monkeypatch):
|
|
monkeypatch.chdir(tmp_path)
|
|
(tmp_path / "a.py").write_text("x = 1\n", encoding="utf-8")
|
|
_cached_source_key.cache_clear()
|
|
for _ in range(100):
|
|
_source_key("a.py", tmp_path)
|
|
info = _cached_source_key.cache_info()
|
|
assert info.misses == 1 and info.hits == 99, info
|
|
|
|
|
|
@needs_cache
|
|
def test_cache_is_cwd_sensitive(tmp_path, monkeypatch):
|
|
"""A relative source_file resolves against CWD; a chdir must not replay
|
|
the previous directory's resolution."""
|
|
d1 = tmp_path / "checkout1"
|
|
d2 = tmp_path / "checkout2"
|
|
for d in (d1, d2):
|
|
d.mkdir()
|
|
(d / "mod.py").write_text("x = 1\n", encoding="utf-8")
|
|
|
|
monkeypatch.chdir(d1)
|
|
k1 = _source_key("mod.py", d1)
|
|
monkeypatch.chdir(d2)
|
|
k2 = _source_key("mod.py", d2)
|
|
assert k1 == "mod.py" and k2 == "mod.py"
|
|
# And cross-root: from d2, resolving against d1's root must fall back to
|
|
# the raw path (out-of-root), exactly as the unmemoized code did.
|
|
assert _source_key("mod.py", d1) == _reference_source_key("mod.py", d1)
|
|
|
|
|
|
@needs_cache
|
|
def test_absolute_path_lookup_skips_getcwd(tmp_path, monkeypatch):
|
|
"""An absolute source_file keys without the cwd, so _source_key never
|
|
calls os.getcwd() for it. A relative one still does."""
|
|
(tmp_path / "a.py").write_text("x = 1\n", encoding="utf-8")
|
|
absolute = str(tmp_path / "a.py")
|
|
assert _cached_source_key is not None
|
|
calls = []
|
|
real_getcwd = os.getcwd
|
|
monkeypatch.chdir(tmp_path)
|
|
assert _source_key("a.py", tmp_path) == "a.py" # warm the memo
|
|
monkeypatch.setattr(os, "getcwd", lambda: calls.append(1) or real_getcwd())
|
|
assert _source_key(absolute, tmp_path) == "a.py"
|
|
assert calls == []
|
|
assert _source_key("a.py", tmp_path) == "a.py"
|
|
assert calls, "a relative path keys on the cwd, even on a memo hit"
|