Rewrite schema merge for efficiency and referential equality#1735
Merged
Rewrite schema merge for efficiency and referential equality#1735
Conversation
eb62c74 to
efa4fea
Compare
efa4fea to
5843307
Compare
arseny-kostenko
approved these changes
Apr 28, 2026
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.
Description
Rewrites
updateSchemaFromEntitiesand its supporting functions to be more efficient and preserve referential equality at every level of the schema when nothing changes. This reduces unnecessary React re-renders when entities are merged into an already-up-to-date schema.Changes
Single-pass merge instead of pre-check + merge — The old code ran
shouldUpdateSchemaFromEntities+hasNewPrefixNamespacesto decide if an update was needed, thenupdateSchemaFromEntitiesrepeated the same work to do the merge. The new code does one merge pass that preserves referential equality when nothing changes, making the pre-check redundant and removing it entirely.Merge directly from entities —
mergeVerticesandmergeEdgeswork directly fromVertex[]/Edge[]instead of first converting to intermediateVertexTypeConfig[]/EdgeTypeConfig[]viamapVertexToTypeConfigs/mapEdgeToTypeConfig, avoiding throwaway allocations.Merge functions return discovered IRIs —
mergeVerticesandmergeEdgesreturn{ configs, newIris }wherenewIriscontains only the type/attribute IRIs that were actually new. This keeps prefix scanning focused on what changed.Optimized prefix scanning —
mergePrefixesonly scans newly-discovered IRIs and entity IDs, rather than re-scanning all existing schema types on every call.Fixed
activeSchemaSelectorsetter churn — The setter allocated a newMapunconditionally, even when the update was a no-op (e.g., returning the same value, or deleting a key that was not present). Now it checksnewValue === prevbefore cloning and guards the RESET/undefined path against no-op deletes.Added
createPrefixTypeConfigfactory — Accepts plain strings{ prefix, uri, inferred? }and produces the brandedRdfPrefix/IriNamespacetypes, reducing manualascasts.Added debug logging — Logs when the schema is updated, when it is already up to date, and when new vertex types, edge types, attributes, or prefixes are discovered.
Benchmarks (70k vertex types, 3 attributes each)
The old code called
getSchemaUrison every merge, which iterated all 70k types and 210k attributes to build aSet<string>— even when nothing changed.The empty schema case is roughly equivalent since there is no existing schema to skip.
New tests
country,country2→country3)schemaAtomnot churned when active config has no schema entryschemaAtomnot churned when entities already match schemaValidation
pnpm checkspasses (lint, format, types)pnpm testpasses (1646 tests across 152 files)Check List
pnpm checkspasses with no errors.pnpm testpasses with no failures.