perf: Extend the JSON-LD fast path to config documents (CSS cold start 16.9 s -> 6.3 s)#6
Draft
jeswr wants to merge 1 commit into
Draft
perf: Extend the JSON-LD fast path to config documents (CSS cold start 16.9 s -> 6.3 s)#6jeswr wants to merge 1 commit into
jeswr wants to merge 1 commit into
Conversation
The initial fast path only covered generator-produced component documents; hand-written config documents always fell back to the generic streaming pipeline, which re-resolves type-scoped contexts for every typed node. Profiling a Community Solid Server cold start showed those per-node scoped-context activations (1,405 distinct resolutions, none repeating within a boot) as the dominant remaining parse cost. This extends the guarded subset with the two features config documents use: - Root-level @graph, including the named-graph form (a root node carrying properties such as `import` alongside @graph names the graph after itself; list cells always land in the default graph, exactly mirroring the generic parser's placement). - Single, non-propagating type-scoped context activation: when a node's @type names a term with a scoped context, that scoped context is resolved ONCE per (context, term) with the real jsonld-context-parser (same options as the generic parser's ParsingContext.parseContext), analyzed, cached on the root entry, and applied to that node only, with nested nodes reverting to the root context (JSON-LD 1.1 non-propagation semantics). Multiple scoped types, propagating or unresolvable scoped contexts, and scoped terms used as keys still fall back. Also fixes double list wrapping for explicit @list objects under @container: @list definitions (previously such documents fell back before reaching the converter, so the case was latent). Correctness: on the full Community Solid Server 7.1.9 boot corpus (828 component documents + 220 config documents), fast-path output is rdf-isomorphic to the generic pipeline for all 1048 files on BOTH the current dependency stack and the componentsjs 5.5.1 stack CSS actually boots with; 1047/1048 take the fast path (the one holdout uses a base-relative @type, which the fast path deliberately leaves to the generic parser). 30 new unit tests cover the @graph and scoped activation matrices; the suite retains 100% coverage. Performance (pss-solid-test, 2-core shared box, alternating arms, fresh data root per boot; backport of this branch onto the installed componentsjs 5.5.1): CSS cold start drops from a 16.0-17.9 s stock median of 16.9 s to 6.2-6.5 s (median 6.3 s) - 2.67x, with 977/978 boot documents fast-pathed. Combined with the earlier module-state work this brings CSS cold boot to the 4-6 s range targeted by the boot-latency roadmap. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends #1's guarded JSON-LD fast path to hand-written config documents — the other half of a Components.js application load. Stacked on #1 (base branch
perf/jsonld-fast-path); review this PR for the extension diff only.Phase-2 profiling showed that after #1, the dominant remaining cost of a Community Solid Server cold start was the generic streaming pipeline re-resolving type-scoped contexts once per typed node in the 145 imported config files (1,405 distinct context resolutions per boot, none repeating — so no context-level cache can absorb them). This PR converts that cost into once-per-(context, term) resolution at analysis time.
What's new in the guarded subset
@graph— including the named-graph form componentsjs configs use ({"@context", "import": [...], "@graph": [...]}): a root node with properties alongside@graphnames the graph after itself; its own quads (e.g. theimport→rdfs:seeAlsolinks that driveRdfStreamIncluder) stay in the default graph. Two mirrored subtleties, both probed against the generic parser and pinned by tests: list cells always land in the default graph even inside named graphs, and@graph-only documents emit into the default graph.@typenames a term carrying a scoped context, that context is resolved once per (context, term) with the realjsonld-context-parser(same options as the generic parser'sParsingContext.parseContext, minus the base IRI: the fast path falls back on anything base-relative, so the merged context is shareable across documents). The merged context is analyzed with the same term classification as the root context and applied to that node only; nested nodes revert to the root context (JSON-LD 1.1 non-propagation, verified against the generic parser). Out of subset (→ fallback): multiple scoped types on one node, propagating (@propagate) or unresolvable scoped contexts, scoped contexts declaring@vocab/@base, scoped terms used as property keys.{"@list": [...]}values under@container: @listdefinitions (found by the config corpus oracle).Correctness evidence
config/ldp/authorization/webacl.json, which uses a base-relative@type("WebAclMetadataCollector") — the fast path deliberately leaves all base-relative IRI resolution to the generic parser.@graphmatrix (default/named/@id-only graphs, lists in named graphs, scalar/array/null entries, null-valued root properties) and the scoped-activation matrix (activation, redefinition, non-propagation, coercion + list containers in scopes, multi-scoped/propagating/@vocab/unresolvable scopes, scoped-as-key). Suite: 1012 tests, 100 % statement/branch/function/line coverage.Performance — CSS cold start (the roadmap number)
Backport of this branch onto the installed componentsjs 5.5.1;
node bin/server.js -c config/file.json→Listening, alternating arms, fresh data root per boot (pss-solid-test, 2-core shared,nice -n 18; ratios are the claim):977/978 boot documents fast-path; −10.6 s off the cold start. This lands CSS cold boot at the 4–6 s boot-latency roadmap target (and composes with #3's faster discovery scan and #4's warm-start persistence, which shave further). A phase-2 side-measurement worth recording: with this PR, an additional normalized-context cache in
jsonld-context-parserno longer helps componentsjs boots (0 cache hits — the fast path caches contexts itself), which simplifies the upstreaming story to this repository alone.Generated by an agent (Claude Fable 5) on @jeswr's behalf — staged on the fork for his review before upstreaming.
Review timing: This draft was prepared with Claude; I (@jeswr) will personally review it before it progresses. I'm currently batching a lot of work in flight, so expect active review Wednesday–Friday (8–10 July).