mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-21 05:59:29 +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
@@ -7,11 +7,16 @@
|
||||
// Parameters: cpgFile, settings, function (optional).
|
||||
// Output: fenced JSON array of {setting, line, method, args, literalArgs}.
|
||||
|
||||
@main def exec(cpgFile: String, settings: String, function: String = "") = {
|
||||
// BATCHED, like taint.sc. Single-request form kept for the committed measurements.
|
||||
|
||||
@main def exec(cpgFile: String, settings: String = "", function: String = "", requests: String = "") = {
|
||||
importCpg(cpgFile)
|
||||
|
||||
def split(raw: String): List[String] = raw.split(",").map(_.trim).filter(_.nonEmpty).toList
|
||||
val names = split(settings)
|
||||
|
||||
def rowsFor(settingsS: String, functionS: String): List[ujson.Obj] = {
|
||||
val names = split(settingsS)
|
||||
val function = functionS
|
||||
|
||||
def matches(name: String): Boolean = names.exists(n => name == n || name == n.split("\\.").last)
|
||||
|
||||
@@ -38,7 +43,19 @@
|
||||
)
|
||||
}
|
||||
|
||||
rows
|
||||
}
|
||||
|
||||
println("---OUSAST-CPG-BEGIN---")
|
||||
println(ujson.write(ujson.Arr(rows: _*)))
|
||||
if (requests.nonEmpty) {
|
||||
val parsed = ujson.read(requests).obj
|
||||
val answers = parsed.map { case (id, req) =>
|
||||
def field(name: String): String = req.obj.get(name).map(_.str).getOrElse("")
|
||||
id -> ujson.Arr(rowsFor(field("settings"), field("function")): _*)
|
||||
}
|
||||
println(ujson.write(ujson.Obj.from(answers)))
|
||||
} else {
|
||||
println(ujson.write(ujson.Arr(rowsFor(settings, function): _*)))
|
||||
}
|
||||
println("---OUSAST-CPG-END---")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user