Skip to content

perf(runtime): share derived defaults and verdicts between occurrences of one shape - #324

Open
devin-ai-integration[bot] wants to merge 43 commits into
feature/fleet-mode-stress-modelfrom
feature/fleet-sparse-runtime
Open

devin-ai-integration[bot] wants to merge 43 commits into
feature/fleet-mode-stress-modelfrom
feature/fleet-sparse-runtime

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

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:

// A `=` default the first pristine occurrence of a shape derived from declared values alone.
type sharedDefault struct {
    value Value        // a scalar held by value: number, string, quantity, complex, enum literal, null
    paths [][]string   // the declared paths it read, rechecked on every occurrence that takes it
}
ctx.sharedDefaults map[sharedKey]*sharedDefault    // sharedKey = {shape, feature}

// A verdict decided on one occurrence within a report, fanned out to the others of its shape.
type sharedVerdict struct {
    result     CheckResult; err error
    paths      [][]string        // must still be as declared on the taker
    inputs     []sharedInput     // values an occurrence states that the check read; must be equal
    classified []*symbols.Symbol
}
memo.verdicts map[verdictKey][]*sharedVerdict      // verdictKey = {element, shape}; one entry per distinct input set
  • Sparse values as shared derived defaults. materializeDerived first asks takeShared:
    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 of sats#(7).eps.battery.mass answers exactly what it
    would have. The derivation is traced (derivationTrace) as it runs: a read of a value the
    occurrence 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.
    SetFeatureValue and dependency invalidation (dependents.go) drop what an occurrence took
    and 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 a
    sequence is derived per occurrence.
  • Verification over distinct shapes. CheckConstraintOn, CheckRequirementOn and
    CheckSatisfactionOn go through checkOn, which — inside a ShareVerdicts span that
    -validate=<object> and the REPL's -satisfy report open — evaluates a check once per
    (element, shape, distinct inputs) and fans the verdict out (sharedVerdict.on) to every
    other 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=0 turns 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
its declared default stores nothing for it": no per-object slot. Instance.FeatureValues is a map
indexed 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 dryMass
and totalPowerDraw, which materialized the component subtree and started its behaviors per
occurrence. So the slot contract is kept, deliberately: every occurrence still has one
FeatureValue per effective feature, and what is shared is the derivation and its result,
recorded per shape in a Context side table. A FeatureValue.intrinsic flag marks a slot whose
value 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.md records this as
⚠️ approximate with the reason.

Two further things the design does not settle, decided here:

  • The fleet's own -satisfy workload never fans out a verdict: every assertion it generates names
    a diverging unit (satisfy blockAMass by network.plane0.unit16), which states its own as-built
    values, so each verdict is its own distinct input set. The halving of -satisfy below comes
    entirely from the shared defaults each evaluation takes. Fan-out is exercised by the
    satisfy_distinct_shapes_mixed conformance case and shared_verdict_test.go; the stress-test
    record says so rather than claiming the workload shows it.
  • A warm re-check — a session in which every value is already materialized — is slower by one to
    four milliseconds per report (BenchmarkFleetSatisfy), because the report still traces what
    each check reads to decide what it may fan out. That is the cost of sharing when there is
    nothing left to share; the cold -satisfy is the case the fleet form is for. Both are in the
    record.

Specification basis

KerML 1.0 §8.3 Feature Values / SysML v2 §7.6: a = default is a property of the feature's
declaration, 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 shared
derived default (⚠️ approximate, per the slot deviation above) and the shared verdict
(✅ faithful). shared_default.go and shared_verdict.go join 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 -memstats and /usr/bin/time -v; the before binary is #308's branch built beside
the 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).

satellites operation before wall allocated peak RSS after wall allocated peak RSS
1 600 -validate 0.20 s 95.8 MiB 105 MB 0.19 s 95.7 MiB 111 MB
1 600 -instantiate SatelliteNetwork::Constellation::network 0.51 s 222.6 MiB 181 MB 0.39 s 217.7 MiB 177 MB
1 600 -satisfy, 324 assertions 1.01 s 515.7 MiB 275 MB 0.59 s 352.9 MiB 249 MB
12 800 -validate 0.63 s 263.6 MiB 191 MB 0.61 s 263.7 MiB 186 MB
12 800 -instantiate SatelliteNetwork::Constellation::network 2.47 s 1.0 GiB 692 MB 1.93 s 1 007.1 MiB 680 MB
12 800 -satisfy, 2 412 assertions 23.2 s 14.4 GiB 1.38 GB 10.9 s 6.1 GiB 1.27 GB
12 800 %eval plane<i>.sats.dryMass, all 32 planes 259 s 74.3 GiB 5.2 GB 8.6 s 2.1 GiB 1.16 GB

The 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:

satellites instantiate + read four planes, before → after allocated warm re-check of every assertion, before → after
32 77 ms → 15 ms 21.3 MiB → 8.0 MiB 0.8 ms → 2.3 ms
128 298 ms → 27 ms 87.1 MiB → 15.1 MiB 1.2 ms → 2.3 ms
512 1.53 s → 68 ms 608 MiB → 44.3 MiB 6.0 ms → 9.9 ms

Recorded in docs/project/satellite-network-stress-test.md (new subsection Sharing derived
defaults and verdicts between the occurrences
) and docs/internals/performance.md.

How it was verified

  • TestSparseValuesDifferential and TestSparseValuesDifferentialFleet
    (sparse_differential_test.go) instantiate every runtime fixture, every execution-conformance
    model 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.
  • Four execution-conformance cases under 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 shared
    value 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 over
    one shape, satisfaction by units, one evaluation per distinct input. robustness_test.go: a
    cyclic derivation and a derivation failing after a write, each the same typed error with
    sharing on and off.
  • Every pre-existing runtime test (conformance, traces, robustness) passes unchanged.
  • The -satisfy reports and the %eval results above were diffed before/after by hand.

Gates, on the merged head:

gofmt -l .                      (nothing)
go build ./...                  ok
go vet ./...                    ok
go test ./...                   ok
go test -race ./...             ok
make docs-check                 0 broken links; no internal labels; changelog fragments valid
make docs-counts                regenerated README.md / spec-compliance.md counts (218 calc cases, 944 conformance, 467 robustness, 8 436 tests)
OPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 \
  go test -count=1 ./internal/core/model -run 'TestTrainingExamples|TestPilotCorpora'
                                100/100 training files clean; kerml-examples 55/58, sysml-examples 95/99,
                                sysml-validation 56/56 — every ratchet where develop leaves it, no expectation changed

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (see CONTRIBUTING.md)
  • Changelog entry added as changes/unreleased/occurrence-shared-defaults.performance.md, not as an edit to CHANGELOG.md
  • baselines regenerated and make docs-counts run if a gate count moved (compliance rows need nothing: the census is counted at docs build)
  • No internal work-item labels (waves, slices, F4, K5) in the body, docs, or changelog

devin-ai-integration Bot and others added 9 commits September 15, 2026 17:53
…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>
…declares

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>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration
devin-ai-integration Bot added this pull request to stack #325 September 15, 2026 19:27
@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review September 15, 2026 19:56
… into feature/fleet-sparse-runtime

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
devin-ai-integration[bot]

This comment was marked as resolved.

…e is not merged with a nested path

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 4 commits September 15, 2026 20:42
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>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 3 commits September 15, 2026 21:15
…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>
devin-ai-integration[bot]

This comment was marked as resolved.

…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>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 22:37
…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
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 22:45
… 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>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 23:10
…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>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 23:56
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
devin-ai-integration[bot]

This comment was marked as resolved.

… into feature/fleet-sparse-runtime

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 4 commits September 16, 2026 03:29
… 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
devin-ai-integration[bot]

This comment was marked as resolved.

… into feature/fleet-sparse-runtime

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration[bot]

This comment was marked as resolved.

… 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
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 16, 2026 18:17
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
devin-ai-integration[bot]

This comment was marked as resolved.

…he type's features

Co-Authored-By: jason.han <hanhuijun@gmail.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