Skip to content

feat(stressmodel): generate the satellite network as a fleet of occurrences - #308

Open
devin-ai-integration[bot] wants to merge 26 commits into
developfrom
feature/fleet-mode-stress-model
Open

devin-ai-integration[bot] wants to merge 26 commits into
developfrom
feature/fleet-mode-stress-model

Conversation

@devin-ai-integration

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

Copy link
Copy Markdown
Contributor

What and why

First of two pull requests implementing one definition, many occurrences from
docs/project/large-model-scaling-design.md §6.
This one rewrites the stress-test constellation in that form and measures what the current
runtime does with it; the second (sparse feature values and verification over distinct shapes
in internal/core/runtime) is #324, stacked on this branch.

Merge order: PR #308 first, then Part B (#324).

cmd/stress-model -fleet generates the satellite network as a fleet:

part def BlockA :> Spacecraft {            // one of four blocks; as-built values as defaults
    attribute :>> catalogId default = 40000;
    part :>> comms { part :>> crosslinkTerminal { attribute :>> mass default = 2.0 [kg]; … } }
    …
}
part def OrbitalPlane {
    part sats : Spacecraft[400] ordered;
    interface ring : RFLink connect [1] sats.comms.crosslinkTx to [1] sats.comms.crosslinkRx;
}
part plane0 : OrbitalPlane {
    part :>> sats : BlockA { attribute :>> plane = 0; }
    part unit16 :> sats {                  // every sixteenth unit diverges from its block
        attribute :>> catalogId = 40016;
        attribute :>> slot = 16;
        part :>> comms { part :>> crosslinkTerminal { attribute :>> mass = 19.9 [kg]; … } }
    }
}
satisfy blockAMass by blockAConfig;        // one check per block …
satisfy blockAMass by network.plane0.unit16;  // … and one per diverging unit

instead of part def Sat0 :> Spacecraft { … }Sat12799. The spacecraft (subsystems,
components, budgets, connections, mode machine), the ground segment and the three requirements
are the ones the single-definition form declares, and every as-built value a block states is a
default so a diverging unit can redefine any of it; that form's output is byte-for-byte
unchanged. Stats gains Definitions and Units so the two
forms compare:

satellites form definitions units elements source
1 600 (8 × 200) one part def per satellite 1 600 1 600 294 627 18.1 MB
1 600 (8 × 200) fleet 4 104 3 203 193 KB
12 800 (32 × 400) one part def per satellite 12 800 12 800 2 354 827 145 MB
12 800 (32 × 400) fleet 4 800 12 467 771 KB

Where the implementation differs from the design. §6 has the per-unit data in a value table
the fleet binds to. Two things stop that today, both documented in the guide chapter and the
stress-test record rather than worked around:

  • A binding bind sats.comms.crosslinkTerminal.serialNumber = serialNumbers onto a feature that
    already has a block-level default is reported as a binding conflict (the default and the table
    are both values of the same feature), and a feature without a default has nothing for the
    non-diverging units to inherit.
  • A literal sequence of 12 800 values is the same size as the declarations it replaces.

The closest conforming form — a member subsetting the fleet (part unit16 :> sats { … }) for
each unit that diverges, inheriting everything else from the block — is what the generator
emits. The runtime places subsetting units as the leading members of sats (sats#(1) is
unit0, sats#(2) is unit16, sats#(3) onward read the block's defaults); the collection
keeps its declared size.

The links are not the same topology. The single-definition form writes every pair: ring
i → i+1 closing each plane, slot i of one plane to slot i of the next, satellite i to
station i mod G. A connector end is a feature chain, not an expression (sats#(1).comms.crosslinkTx
is not an end), so the fleet form cannot state those pairs without naming every occurrence; it
declares one connector over each collection instead — connect [1] sats.comms.crosslinkTx to [1] sats.comms.crosslinkRx, one per adjacent pair of planes, one per plane and station — whose [1]
ends say each link joins one satellite to one satellite or station, not which. The runtime
realizes such a connector as one link whose ends hold the collections (network.plane0.ring.a is
every transmitter of the plane), whatever the end multiplicities declare. The guide chapter and
the stress-test record say so; the fleet figures below are for that model, not for a pairwise one.

What the current runtime does with the fleet (measured; the second pull request changes
this). Instantiation still creates an object with a value slot per feature for every
occurrence, and materialization of the created network is bounded by maxMaterializeBudget. A
satisfy whose subject is a collection (plane0.sats) is rejected — the subject must denote
one object — so the assertions target each block's configuration and each diverging unit. A
usage whose multiplicity lower bound exceeds 1 000 cannot be materialized, so the fleet is laid
out as 32 planes of 400 rather than 8 of 1 600.

Measurements

Intel Xeon Platinum 8559C, 8 CPUs, 31 GiB RAM, no swap, Linux, Go 1.25, GOMAXPROCS=8.
Wall is sysml wall-clock, allocated is runtime.MemStats.TotalAlloc, RSS is /usr/bin/time
maximum resident set. Same plane/station layout in each pair of rows.

-validate:

satellites form elements wall allocated peak RSS
1 600 one part def per satellite 294 627 17.5 s 5.5 GiB 2.6 GB
1 600 fleet 3 203 0.17 s 93 MiB 106 MB
12 800 one part def per satellite 2 354 827 301 s 43.5 GiB 20.1 GB
12 800 fleet 12 467 0.57 s 254 MiB 175 MB

The stress-test record's earlier 12 800-satellite figure (318 s / 44.0 GiB / 20.6 GB) was taken
with a different plane/station split and is kept beside these, labelled as such.

Current runtime on the fleet form:

satellites operation wall allocated peak RSS
1 600 -instantiate the network 0.47 s 220 MiB 168 MB
1 600 -satisfy, 324 assertions 0.95 s 513 MiB 269 MB
12 800 -instantiate the network 2.34 s 1.0 GiB 692 MB
12 800 -satisfy, 2 412 assertions 23.4 s 14.4 GiB 1.36 GB
12 800 %eval of sats.dryMass in all 32 planes 252 s 73.8 GiB 4.9 GB

A CPU profile of the 16-plane -satisfy spends 57% in expression evaluation (41% of the total
starting the behaviors of the parts evaluation materializes) and 31% polling running state
machines for due events — the costs the second pull request targets.

go test ./internal/stressmodel -run '^$' -bench Fleet -benchmem -benchtime 3x:

BenchmarkFleetInstantiate/satellites=32/elements=1179-8      3    73743460 ns/op   2304483 ns/satellite    21293224 B/op    360948 allocs/op
BenchmarkFleetInstantiate/satellites=128/elements=1715-8     3   268175526 ns/op   2095121 ns/satellite    87005618 B/op   1323968 allocs/op
BenchmarkFleetInstantiate/satellites=512/elements=3947-8     3  1431257219 ns/op   2795424 ns/satellite   607197090 B/op   5176204 allocs/op
BenchmarkFleetSatisfy/satellites=32/assertions=24-8          3      807915 ns/op                            518040 B/op      7360 allocs/op
BenchmarkFleetSatisfy/satellites=128/assertions=36-8         3     1420513 ns/op                           1127277 B/op     11282 allocs/op
BenchmarkFleetSatisfy/satellites=512/assertions=108-8        3     6354922 ns/op                           7774328 B/op     33968 allocs/op

Recorded in docs/project/satellite-network-stress-test.md (new section) and
docs/internals/performance.md; docs/guide/modeling-fleets.md is the new guide chapter, linked
from the guide index and the mkdocs.yml nav.

How it was verified

  • internal/stressmodel/satnet_test.go: TestFleetValidates loads a 2 × 32 fleet strictly with
    no diagnostics, checks every satisfy verdict holds, and reads inherited values
    (sats#(3).catalogId, sats#(3).plane, sats#(3).comms.crosslinkTerminal.dataRate,
    sats#(3).eps.solarArray.area), diverging values (unit0, unit16, sats#(1), sats#(2),
    unit16.comms.crosslinkTerminal.dataRate) and satelliteCount through the instantiated
    network, and checks the block details are written default = and the collection connectors
    declare [1] ends; TestFleetScales checks that
    more occurrences add no definitions, that only diverging units add declarations, that more
    planes add definitions and links, and that the fleet source is far smaller than the
    single-definition source.
  • internal/stressmodel/bench_test.go: BenchmarkFleetInstantiate, BenchmarkFleetSatisfy.
  • The single-definition generator's output was diffed byte-for-byte against develop's for the
    test layouts: identical.
  • gofmt -l . prints nothing; go build ./..., go vet ./..., go test ./...,
    go test -race ./... pass; make lint passes.
  • Corpus gates with the corpora present:
    OPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 go test -count=1 ./internal/core/model -run 'TestTrainingExamples|TestPilotCorpora'
    — training 100/100 clean, training_examples_expected.txt unchanged and empty; pilot ratchets
    unchanged (kerml-examples 55/58, sysml-examples 95/99, sysml-validation 56/56).
  • make docs-check (links, internal-label scan) passes; make docs-counts regenerated the test
    counts in README.md and docs/project/spec-compliance.md for the two new tests;
    python3 scripts/changelog.py check passes.

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/<slug>.<section>.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

…rences

Add a fleet form to the stress-model generator (cmd/stress-model -fleet):
four spacecraft blocks carry the as-built values as defaults, each orbital
plane is 'part sats : Block[N] ordered', and only every sixteenth unit states
values of its own, as a member subsetting the plane's fleet. The spacecraft,
ground segment, requirements, mode machine, ring, inter-plane and downlink
connectors are those of the single-definition form, whose output is
unchanged. Stats gains Definitions and Units so the forms compare.

At 12 800 satellites the fleet declares 11 667 elements against 2 354 827
and validates in 0.57 s and 185 MB rather than 301 s and 20.1 GB. The guide
chapter on modeling fleets shows both forms, the stress-test record and the
performance notes carry the measurements, including what the current
runtime pays to instantiate, check and read the occurrences, and
BenchmarkFleetInstantiate and BenchmarkFleetSatisfy time it.

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 marked this pull request as ready for review September 15, 2026 07:20
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 3 commits September 15, 2026 07:40
… state link cardinality

Block component details (array area, battery capacity, terminal data rate, …)
are now defaults like the masses and serial numbers, so a diverging unit can
redefine them; the crosslink terminal of every diverging unit states its data
rate. The ring and inter-plane collection connectors declare [1] ends, and the
guide, stress-test record and changelog say what a collection connector does
and does not state about the per-pair topology. Fleet figures re-measured.

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 2 commits September 15, 2026 16:54
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
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 16:58
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-stress-model

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

# Conflicts:
#	README.md
…-end fix

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

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

# Conflicts:
#	README.md
#	docs/project/satellite-network-stress-test.md
#	docs/project/spec-compliance.md
#	internal/stressmodel/satnet_test.go
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 18:17
…tellation

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration Bot and others added 3 commits September 15, 2026 19:59
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration Bot and others added 4 commits September 15, 2026 22:41
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration Bot and others added 7 commits September 16, 2026 03:28
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

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

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
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