Skip to content

perf(check): load SHACL shapes once per scoped check - #415

Merged
EthanThatOneKid merged 1 commit into
mainfrom
shacl-scoped-shapes-once
Oct 19, 2026
Merged

EthanThatOneKid merged 1 commit into
mainfrom
shacl-scoped-shapes-once

Conversation

@EthanThatOneKid

Copy link
Copy Markdown
Collaborator

What

A scoped wiki check FILE... (which build --only and the file watcher also use) called checkShaclFile once per file. Each call re-extracted the shapes graph with loadShapes, which scans every quad in the corpus several times (shacl.ts:88-154). A scoped check of k files cost O(k × corpus) for shapes that never change between files.

  • shacl.ts: new loadWikiShapes(config) (the uninferred graph's shapes, the same expression checkShaclFile used inline). checkShaclFile takes an optional third shapesGraph, which defaults to loadWikiShapes(config), so existing callers and the public API behave the same.
  • audit.ts: runCheck builds the shapes once per scoped check and passes them to each file.
  • mod.ts: exports loadWikiShapes alongside checkShaclFile, so in-process callers can do the same.

This is item 1 of "Where Wiki's cost grows with corpus size" in #414.

Measured

A generated wiki of 2,000 Person pages plus one node shape, wiki check on 50 of them, two runs each, Windows:

Run 1 Run 2
main @ a7074ee 73.5 s 102.6 s
this branch 12.5 s 15.0 s

A single-file scoped check on the same wiki takes about 10 s, which is mostly the graph load the cache already covers. So almost all of the remaining time for 50 files is fixed cost, not per-file cost. I also checked by hand that an invalid page still reports shacl_violation alongside a valid one.

Checks

deno task check, deno task lint, deno task fmt:check, and deno task test (574 passed, 1 ignored). The new test asserts that a passed-in shapes graph is used as given: the wiki's own shapes give the same result as the default, and an empty graph has nothing to violate.

Not changed

Refs #414

🤖 Generated with Claude Code

A scoped `wiki check FILE...` (also `build --only` and the watcher) called
`checkShaclFile` once per file, and each call re-extracted the shapes graph
with `loadShapes`, which scans every quad in the corpus several times. A
scoped check of k files cost O(k x corpus) for the same shapes every time.

`runCheck` now builds the shapes once with the new `loadWikiShapes` and passes
them to `checkShaclFile`, which takes an optional `shapesGraph` and still
defaults to loading the shapes itself, so existing callers are unchanged.

On a generated 2,000-page wiki, a 50-file scoped check went from 73-103 s to
12-15 s.

Refs #414

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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