Repository navigation
Reduce the repeated validation and allocation - #11
Merged
Merged
Conversation
| Fixed cutoff | Mean direct-counter time | Relative to best | |---|---:|---:| | unrolled only | 3,484.12 ns/op | +1.31% | | <= 64 bytes | 3,475.09 ns/op | +1.04% | | <= 128 bytes | 3,457.94 ns/op | +0.55% | | **<= 256 bytes** | **3,439.16 ns/op** | **best** | | <= 384 bytes | 3,441.56 ns/op | +0.07% | | <= 512 bytes | 3,466.82 ns/op | +0.80% |
…nalProperties keywords
…and reduce scope-scanner traversal
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.
Reduce string-length counting allocations to
minLengthandmaxLength.Direct predicate pass cases
Median µs/op, long inputs:
minLengthbefore → aftermaxLengthbefore → afterBoth predicates improve materially for long strings: roughly 1.55×–2.53× faster, depending on UTF-8 width.
Public validation with both keywords
The combined
minLength+maxLengthvalidation path is about 1.57×–2.48× faster for these long-input workloads.Share regex compilation between sibling object keywords
patternPropertiesandadditionalProperties, each successful pattern regex is compiled once and reused.$defsordering, vocabulary gates, regex-error paths, child-schema error paths, rule order, and compiled rule shapes are preserved.additionalProperties: false: before → afteradditionalProperties: true: before → afterAvoid repeated runtime pattern classification
validate_entry/5invocation;patternPropertiesvalidations;$ref/ loaders;For 512 unmatched keys and 512 patterns:
patternProperties→additionalPropertiesadditionalProperties→patternPropertiesThe reverse order deliberately retains checks for later overlapping patterns. Pattern-only controls remain effectively unchanged; all-declared-property inputs have no duplicated classification to remove, so no speedup is claimed there.
Reduce evaluated-key set/list round trips when validate
anyOfanyOfwith at least four child schemas and an incoming evaluated-key set of at least eight entries. This keeps ordinary, small, and empty-parentanyOfcalls on their prior reducer.evaluatedset. Successful branches are all visited, including later$refbranches; evaluated keys from earlier branches are never supplied to a later child.%MapSet{}values and tracks their total cardinality. It uses balanced pairwiseMapSet.union/2only when the known shared incoming evaluated keys make up at least two thirds of successful child evaluated-key memberships and at least four children succeed.%MapSet{}accumulator into the exact list-accumulator shape used before P8 and resumes the original reducer. A later branch is deliberately not allowed to restore direct merging: this conservative cutoff avoids retaining a losing raw-set buffer.validate_anyOf/5; other applicator paths retain their existing result-handling path.MapSet.union/2would preserve arbitrary list-valued Elixir keys, whereas the historic list-rebuild path recursively flattens them. After a candidate direct merge, the deduplicated evaluated-key set is checked once; if it contains a list value, the code reruns the historic bulk merge exactly. JSON object property names remain strings, and no non-JSON legacy behavior changes.anyOfsuccess; all-failed error order remains source order.These are synthetic
anyOfvalidation workloads, not general application speedup guarantees.anyOf, parent=16, one new evaluated key/branchanyOf, parent=16, one new evaluated key/branchanyOf, parent=16, one new evaluated key/branchanyOf, parent=16, one new evaluated key/branchanyOfbypassThe parent-dominated target shape eliminates repeated conversion of the same incoming evaluated keys. It reduced reductions by 8.1% at width 4 and by 32.2%–39.1% at widths 16–128; wall time was 56.9%–67.7% lower in this run. The two bypass controls remain within run variation, so no broad
anyOfspeedup is claimed. An immediate fallback also has no claimed speedup. The deliberately conservative late-fallback case pays 5.3% more reductions to convert its retained successful-branch prefix and then resume bulk merging; its 6.0% wall time increase is reported as a workload-specific cost, not a semantic change.Reduce repeated error-list flattening call validation
%Error{}lists now pass through unchanged. Nested error groups and legacy tuple entries are flattened and formatted in one traversal.unevaluated*rewriting remain unchanged; a broader internal error-tree mode is deferred.validation_error_listtype thatvalidate_entry/5already returns.allOfanyOfoneOfunevaluatedPropertiesWide flat errors consistently remove roughly one quarter of reductions, while 128-branch failed applicators remove about 29%. False-schema rewriting also benefits because its already-rewritten flat list no longer gets rebuilt at the
public boundary. The valid primitive control remains at 14 reductions. At deep property depth 128, unchanged internal flattening dominates and wall time is within variation; no speedup is claimed for that shape.
Remove redundant input-key presence checks when validating
requiredN/A
Avoid rescanning built-in Draft 2020-12 resources after compilation, and reduce scope-scanner traversal
#metaidentity, so built-in family construction no longer repeats the same raw-resource scope scan after each compilation.ScopeScannernow reduces scope-bearing children directly. The existingMap.values/1order remains explicit for map-valued keywords, preserving duplicate-identity and anchor overwrite precedence.The traversal benchmark validates production and benchmark-only reducer outputs
with
===before measurement. Each row reports median milliseconds per completeScopeScanner.scan/1operation from five adaptive batches targeting 20 ms;result verification, input/source construction, warmup, and explicit GC are outside
measurement. Before reloads
schema_traversal.exandscope_scanner.exfrom8bef311(combined_sha256=edbd1e34600a82044f14332fc9e5f27904cb312211b10cf79004be8c2ec7ce5b);after uses the working tree
(
combined_sha256=c85cb18db066cc54e092a7e1f7aa7c8421224ee6f2125bc8d7efb11cfc6b2fc8).properties, 1,024 schemasproperties, depth 1,024