perf(runtime): share derived defaults and verdicts between occurrences of one shape - #324
Open
devin-ai-integration[bot] wants to merge 43 commits into
Open
devin-ai-integration[bot] wants to merge 43 commits into
devin-ai-integration[bot] wants to merge 43 commits into
Conversation
…s of one shape A `=` value derived on an occurrence from nothing but what its declarations materialize is kept per shape and feature in a Context side table; every other occurrence of the shape whose reads are still as declared takes it without materializing what it would read. The feature value slot stays, so a value taken this way reads and invalidates exactly as one derived in place. Within a ShareVerdicts span a constraint, requirement or satisfaction check on an occurrence is decided once per shape and distinct input and fanned out to the other occurrences, with subject, path, message and order unchanged. Sparse-on/off differential tests over the fixtures, the conformance models and the generated fleet, plus conformance cases for shared defaults, a default over a diverged sibling, a diverging occurrence table and mixed verdicts over distinct shapes. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… into feature/fleet-sparse-runtime
… into feature/fleet-sparse-runtime
…declares Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ype directly Co-Authored-By: jason.han <hanhuijun@gmail.com>
…s and compliance status Co-Authored-By: jason.han <hanhuijun@gmail.com>
…rse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
6 tasks
… into feature/fleet-sparse-runtime
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md
…e is not merged with a nested path Co-Authored-By: jason.han <hanhuijun@gmail.com>
A traced context shares no derived default or verdict, so the trace records every evaluation as the materializing path makes it. A held image carries whether a value is as declared, what its shape's derivation read, and what a value taken from the shape still owes materializing, so a restored object shares on and settles as the imaged one would. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…r verdict Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…collection A default derived over a collection is owed for each element the derivation read that the taking occurrence has not materialized, not only the last one. Also covers that a condition deciding on its subject's identity is never shared. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md
…ty verdicts Co-Authored-By: jason.han <hanhuijun@gmail.com>
…the shared tables Evaluating `all T` enumerates the run's objects, which no shape names, so a derived default or verdict that reads the extent is the occurrence's own and another occurrence of the shape must see the objects made since. Co-Authored-By: jason.han <hanhuijun@gmail.com>
A probe's or a snapshot's rollback undoes the take itself, so the count is undone through the same journal instead of being captured apart from it. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ld image An assumed population is fixed by multiplicity alone, so a value derived over it is never shared; materialized from an image it read as declared. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md
Adoption derives every taken value again, so the object owes nothing for one; an image records a value as owed only while it still holds what it took. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ared A lifetime is the run's, not the shape's: reading one through isDuring, or ending one, makes every derivation under way its occurrence's own. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com>
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md
A requirement checked directly on the objects carrying it and a satisfaction of it by those objects were shared under one key, so a satisfaction could take the direct verdict and report it under the requirement kind, and a direct check could take a satisfaction's subject-bound verdict. The kind of check now keys the memo; satisfactions of one shape still share among themselves. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md # internal/core/runtime/robustness_test.go
A default or check that draws from the modeled stream is the run's, not the shape's: the draw marks every open sharing trace as the occurrence's own, so each occurrence draws for itself and the seeded stream is consumed once per occurrence. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… into feature/fleet-sparse-runtime Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # docs/project/spec-compliance.md
…he type's features Co-Authored-By: jason.han <hanhuijun@gmail.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.
What and why
Second of two pull requests implementing one definition, many occurrences from
docs/project/large-model-scaling-design.md§6.The first, #308, generates the stress-test constellation as a fleet of occurrences and measures
what the runtime did with it; this one makes the runtime treat the occurrences of one shape as
what they are — one definition — instead of deriving and checking each as if it were declared on
its own. It is stacked on #308's branch.
Merge order: PR #308 first, then Part B.
The runtime gains two side tables of the
Context(shared_default.go,shared_verdict.go),keyed by an interned shape — the object's type, its classifiers and the feature holding it:
materializeDerivedfirst askstakeShared:a pristine occurrence of a shape whose feature another pristine occurrence already derived
takes the recorded value without evaluating the default or materializing the subtree the
derivation walked (the component tree, its own derived masses, its classifier behaviors).
Everything that subtree would have materialized is owed and settled the moment anything asks
for it (
settleOwed), so a later read ofsats#(7).eps.battery.massanswers exactly what itwould have. The derivation is traced (
derivationTrace) as it runs: a read of a value theoccurrence states, a binding, a write, a behavior attached, a classification or a redefinition
anywhere along the read paths marks it unshareable, and that occurrence derives on its own.
SetFeatureValueand dependency invalidation (dependents.go) drop what an occurrence tookand un-share the traces under way, so a write after a take never leaves a stale shared value.
Only scalars held by value are shared (
shareable): a default whose value is an object or asequence is derived per occurrence.
CheckConstraintOn,CheckRequirementOnandCheckSatisfactionOngo throughcheckOn, which — inside aShareVerdictsspan that-validate=<object>and the REPL's-satisfyreport open — evaluates a check once per(element, shape, distinct inputs)and fans the verdict out (sharedVerdict.on) to everyother occurrence whose declared reads are still as declared and whose stated inputs are equal,
with that occurrence's own subject path. A check that read a value the occurrence states, ran
a behavior or errored is evaluated on that occurrence. Verdicts, messages and order are those
of evaluating every check.
OPENSYSML_SHARED_DEFAULTS=0turns both off; nothing else about the runtime's surface changes.Where the implementation differs from the design. §6.2 has "an occurrence whose feature holds
⚠️ approximate with the reason.
its declared default stores nothing for it": no per-object slot.
Instance.FeatureValuesis a mapindexed by about 380 sites in the runtime, the REPL, the gRPC service and their tests, every one
expecting a slot per effective feature, and on the fleet the slots are ~17 KB of the ~45 KB an
occurrence costs; the cost §6 is after — ≈1 MiB and 2 ms per occurrence — is deriving
dryMassand
totalPowerDraw, which materialized the component subtree and started its behaviors peroccurrence. So the slot contract is kept, deliberately: every occurrence still has one
FeatureValueper effective feature, and what is shared is the derivation and its result,recorded per shape in a
Contextside table. AFeatureValue.intrinsicflag marks a slot whosevalue the declarations alone produced, which is what makes it eligible to be shared and what a
write clears. The compliance row in
docs/project/spec-compliance.mdrecords this asTwo further things the design does not settle, decided here:
-satisfyworkload never fans out a verdict: every assertion it generates namesa diverging unit (
satisfy blockAMass by network.plane0.unit16), which states its own as-builtvalues, so each verdict is its own distinct input set. The halving of
-satisfybelow comesentirely from the shared defaults each evaluation takes. Fan-out is exercised by the
satisfy_distinct_shapes_mixedconformance case andshared_verdict_test.go; the stress-testrecord says so rather than claiming the workload shows it.
four milliseconds per report (
BenchmarkFleetSatisfy), because the report still traces whateach check reads to decide what it may fan out. That is the cost of sharing when there is
nothing left to share; the cold
-satisfyis the case the fleet form is for. Both are in therecord.
Specification basis
KerML 1.0 §8.3 Feature Values / SysML v2 §7.6: a⚠️ approximate, per the slot deviation above) and the shared verdict
=default is a property of the feature'sdeclaration, evaluated against the object holding it; the shared value is the same evaluation,
recorded once per shape and rechecked against every occurrence that takes it. Two rows added to
the Instantiation and Feature Values map in
docs/project/spec-compliance.md: the sharedderived default (
(✅ faithful).
shared_default.goandshared_verdict.gojoin the runtime file table.Measurements
Machine: Intel Xeon Platinum 8559C, 8 cores, 31 GiB RAM, no swap, Go 1.25.0 linux/amd64. One run
each with
-memstatsand/usr/bin/time -v; the before binary is #308's branch built besidethe after and run the same hour. The fleet at 1 600 satellites is 3 203 elements, at 12 800 it
is 12 467 (against 294 627 and 2 354 827 in the one-definition-per-satellite form).
-validate-instantiate SatelliteNetwork::Constellation::network-satisfy, 324 assertions-validate-instantiate SatelliteNetwork::Constellation::network-satisfy, 2 412 assertions%eval plane<i>.sats.dryMass, all 32 planesThe satisfaction reports are identical line for line (2 412 verdicts, same order) and the 12 800
masses agree. For the record's historical single-definition figures — 318 s / 44 GiB allocated /
19.7 GiB RSS to validate 12 800, 83 s / 7.2 GiB RSS to satisfy 3 200 — the fleet form validates
12 800 in 0.6 s / 264 MiB / 186 MB and satisfies 12 800 in 10.9 s / 6.1 GiB / 1.27 GB.
BenchmarkFleetInstantiate/BenchmarkFleetSatisfy(go test ./internal/stressmodel -run '^$' -bench Fleet -benchmem -benchtime 3x), warm:Recorded in
docs/project/satellite-network-stress-test.md(new subsection Sharing deriveddefaults and verdicts between the occurrences) and
docs/internals/performance.md.How it was verified
TestSparseValuesDifferentialandTestSparseValuesDifferentialFleet(
sparse_differential_test.go) instantiate every runtime fixture, every execution-conformancemodel and generated fleets with sharing on and off, and compare every readable value of every
held object and every verdict of every check, plus the diagnostics each side reports.
internal/core/runtime/testdata/conformance/:occurrence_default_shared,occurrence_default_over_diverged_sibling,occurrence_table_diverging_units,satisfy_distinct_shapes_mixed.shared_default_test.go: the value kinds shared and those derived per occurrence, a sharedvalue followed by divergence and a diverged occurrence never sharing, a later write under a
subtree a shared derivation read, sharing off, sharing under classification, a failing
derivation never shared, a held image round trip.
shared_verdict_test.go: mixed verdicts overone shape, satisfaction by units, one evaluation per distinct input.
robustness_test.go: acyclic derivation and a derivation failing after a write, each the same typed error with
sharing on and off.
-satisfyreports and the%evalresults above were diffed before/after by hand.Gates, on the merged head:
Checklist
make testandmake lintpass locallychanges/unreleased/occurrence-shared-defaults.performance.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (compliance rows need nothing: the census is counted at docs build)F4,K5) in the body, docs, or changelog