Skip to content

perf: cache _source_key and make _walk_python_tree iterative - #2765

Open
EinWenigDaneben wants to merge 1 commit into
Graphify-Labs:v8from
EinWenigDaneben:graphify-optim
Open

perf: cache _source_key and make _walk_python_tree iterative#2765
EinWenigDaneben wants to merge 1 commit into
Graphify-Labs:v8from
EinWenigDaneben:graphify-optim

Conversation

@EinWenigDaneben

Copy link
Copy Markdown

What

Two extraction-path performance improvements.

  1. Cache _source_key filesystem resolution (graphify/extractors/resolution.py) — memoize on (source_file, root), cleared once per extract() run; skips repeated stat/realpath syscalls per node/edge/raw_call.

  2. Iterative _walk_python_tree — replace the recursive generator (yield from re-forwards every descendant through the call chain, O(depth) per node) with an explicit-stack pre-order walk; each node yielded exactly once. Same node order.

Evidence

Single-worker extract on a 357-file PHP corpus, best-of-3:

min
baseline (no patch) 2.20 s
with patch 1.18 s

~46% faster on the measured corpus.

Tests

tests/test_hermes_verified_optimizations.py locks pre-order identity of the iterative walk + _source_key memo stability. Rest of the suite: only pre-existing failures (test_skillgen, test_ollama_retry_cap) which also fail on unpatched v8.

- Memoize _source_key((source_file, root)) to skip repeated filesystem
  stat/realpath calls per node/edge/raw_call during extraction.
- Replace recursive generator in _walk_python_tree with an iterative
  pre-order stack walk so large tree-sitter trees no longer re-forward
  every descendant through the call chain.
- Add regression tests locking pre-order identity and memo stability.

Measured ~46% faster single-worker extract on a 357-file PHP corpus
(2.20s -> 1.18s best-of-3).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. 1 change(s) tested, no difference found (not proven).


Graphify review — findings

This PR applies two performance-oriented changes in the resolution extractor. It adds a module-level _SOURCE_KEY_CACHE memo to _source_key (keyed by source_file and root) and clears it at the start of each extract() run, and it rewrites _walk_python_tree from a recursive yield from generator into an iterative explicit-stack pre-order DFS. It also adds a new test file (test_hermes_verified_optimizations.py) that checks the iterative walk matches the previous recursive traversal order and that _source_key memoization returns stable results and populates the cache. The changed-symbols list is broad, but the actual diff touches only extract.py, resolution.py, and the new test file.

No blocking issues surfaced. 1 lower-confidence candidate did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 1654 functions depend on the 334 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 454 callers, 41 callees
  • new: _rebuild_code() — 95 callers, 51 callees
  • new: _extract_generic() — 18 callers, 23 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_objc() — 27 callers, 9 callees
  • new: dispatch_command() — 2 callers, 117 callees
  • new: extract_js() — 76 callers, 3 callees
  • new: _resolve_js_module_path() — 27 callers, 6 callees
  • …and 38 more

Verification — 1654 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 1514 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

Could not verify: Could not verify \_source\_key.

The verifier did not have enough to check \_source\_key, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `root` is annotated `Path` — outside the synthesizable primitive/collection set

No difference found (not proven): No behavior difference found in \_walk\_python\_tree (not a proof).

The verifier ran both versions of \_walk\_python\_tree on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: concolic exploration (CrossHair). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

· 46 more finding(s) on lines outside this diff (see the check run).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant