mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
perf(model): one Joern invocation per query kind, not one per region
JVM startup dominated a scan: a call per region per family put a ten-line file at 275s over three regions, and would have put a thousand regions at roughly fifty hours. The queries themselves are milliseconds once the CPG is loaded, so the cost was almost entirely process starts. scan_repository() is now collect -> batch -> arbitrate. The three .sc scripts accept a `requests` JSON map and answer all of them in one run, keeping the single-request form so the committed measurements stay reproducible byte-for-byte. Arbiters are untouched: each is handed a CpgResult whose `run` returns its own prefetched rows. The batcher builds parameters by calling request_params() extracted from taint.py, dominance.py and config_value.py rather than reconstructing them. A second copy that drifts from the arbiter's is the exact shape of the five family-assumption bugs the predecessor spec spent a session finding; there is now one definition per family and the batcher borrows it. Regions are also deduplicated by (path, function), collapsing the nameless entry-point rows that were producing `model:injection:?:10`. Measured on the same ten-line file: 275s -> 106s, three duplicate findings -> one `model:injection:ping:10`, rung unchanged at model_entailed. Gates byte-identical. Server mode is recorded as task 2.3, deliberately sequenced after the repository measurement: whether the remaining ~100s floor is worth a process model, a weakened subprocess seam and a Scala-evaluating HTTP endpoint depends on a build-time-to-query-time ratio only 2.2 produces. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
This commit is contained in:
co-authored by
Claude Opus 5
parent
e67f3ee2f0
commit
c35426e186
@@ -145,3 +145,44 @@ def test_a_region_is_only_asked_about_families_it_carries() -> None:
|
||||
|
||||
scan_repository(Path("/repo"), (_region(families=("injection",)),), backend=_B(), client=None, model="")
|
||||
assert "dominance" not in asked and "config" not in asked
|
||||
|
||||
|
||||
def test_the_driver_issues_one_query_invocation_per_kind_not_one_per_region(tmp_path) -> None:
|
||||
"""Task 1.4: JVM startup, not CPG construction, is what dominates a repository scan.
|
||||
|
||||
Before batching the driver issued one `joern --script` call per region per family. A ten-line Python file
|
||||
admits six families, so it cost six JVM launches and over four minutes; a thousand regions would have
|
||||
taken about fifty hours. The whole scan's questions now go in one invocation per query kind.
|
||||
"""
|
||||
from openultrasast.model.scan import scan_repository
|
||||
|
||||
invocations: list[str] = []
|
||||
|
||||
class _CountingBackend:
|
||||
def available(self): # type: ignore[no-untyped-def]
|
||||
return True
|
||||
|
||||
def build(self, root): # type: ignore[no-untyped-def]
|
||||
from openultrasast.cpg.backend import CpgResult
|
||||
|
||||
def run(query, params): # type: ignore[no-untyped-def]
|
||||
invocations.append(f"single:{query}")
|
||||
return []
|
||||
|
||||
def run_batch(query, requests): # type: ignore[no-untyped-def]
|
||||
invocations.append(f"batch:{query}")
|
||||
return {rid: [] for rid in requests}
|
||||
|
||||
result = CpgResult(cpg_path=Path("c.bin"), run=run)
|
||||
object.__setattr__(result, "run_batch", run_batch)
|
||||
return result
|
||||
|
||||
source = "import os\n\n\ndef run(cmd):\n os.system(cmd)\n"
|
||||
for i in range(30):
|
||||
(tmp_path / f"f{i}.py").write_text(source)
|
||||
regions = tuple(_region(path=f"f{i}.py", families=("injection", "path")) for i in range(30))
|
||||
|
||||
scan_repository(tmp_path, regions, backend=_CountingBackend(), client=None, model="")
|
||||
assert not any(i.startswith("single:") for i in invocations), f"unbatched calls remain: {invocations[:4]}"
|
||||
# 30 regions x 2 families would have been 60 invocations; batching makes it one per query kind.
|
||||
assert len(invocations) <= 3, f"expected one invocation per query kind, got {len(invocations)}"
|
||||
|
||||
Reference in New Issue
Block a user