- name
- performance-profiling
- description
- Diagnose or improve LunCoSim FPS, physics time, periodic stalls, Builder versus View differences, terrain/render cost, or Tracy captures. Use when performance must improve architecturally without changing BigSpace, substeps, shadows, terrain quality, or image fidelity.
# Performance profiling: measure the owner, then remove avoidable work
Read the current handover in
[`docs/reviews/open-400fps-performance-handover.md`](../../docs/reviews/open-400fps-performance-handover.md)
before changing code. A status-bar FPS number is a symptom, not an attribution.
## Required separation
- Run one production session that you own for the product FPS number, launched
from the task checkout on a verified free API port. Do this even if another
user's or agent's session is active; never control, stop, restart, or change
the scene in a pre-existing session. Report concurrent GPU/CPU workloads and
classify affected numbers as contention-affected, not clean acceptance. Do
not use Tracy's instrumented number as acceptance evidence.
Record the admitted Twin source revision and require its expected authored
verdict before comparing completed-mission windows. A tick threshold or zero
process exit does not prove acceptance. Exclude source/API errors, and require
readiness and diagnostics to pass for the measured cohort.
- Run a separate Tracy build/capture using the adjacent `../tracy` checkout;
start `tracy-capture` before the production binary and inspect the settled
window, not only startup.
Check the profiler listener and connection against the owned PID with
`ss -ltnp`/`ss -tnp`. A concurrent Tracy client can occupy 8086 and move the
owned app to the next port; pass that port with `tracy-capture -p`. A capture
from another process is not evidence for the task scene.
A zero collector exit does not prove capture integrity. Compare the saved
file size with the collector's reported compressed payload plus native file
framing, and require a successful native CSV export before using its zones.
`FileWrite::GetCompressionStatistics` excludes the six-byte file header and
four-byte length per compressed block; these bytes are present on disk. A size
mismatch,
parser failure or stalled export leaves that capture unusable. A reported
instrumentation failure also makes the requested window incomplete. Keep hot
zone names bounded: step ids, timestamps, and measured durations must not be
span fields when the Tracy layer uses those values as source-location identity. Inspect the
exact owned exporter process before terminating an unsuccessful read; do not
restart a still-running export solely because an observation timed out.
Check disk space while the owned app is live as well as after it exits.
Native capture writing can overlap runtime allocations, and the collector
can report success despite a truncated file.
Native unwrapped CSV rows are grouped by source location; sort by
`ns_since_start` before reconstructing chronological phases or transitions.
- Compare Builder and View with the same scene, camera, rendering-quality
settings, physics substeps, shadow settings, and terrain assets. A Builder-
only cost usually means an editor observer, rebuild, projection, or UI path,
not that physics needs a different global timestep.
- For a settled DEM quality window, require `TerrainLodStatus.stream.wanted ==
resident`, `stream.pending == 0`, `derived.active == false`,
`derived.pending == 0`, and `derived.ready == derived.total`. Record those
owner facts before and throughout the window alongside camera and quality
inputs. Simulation readiness alone does not certify optional visual-map
preparation. Keep this measurement gate out of simulation admission.
Audit a surface camera with `world_pos` and `world_rotation` in the active
simulation frame; `visual_foci` reports composed root coordinates, which move
with celestial ancestors even when the camera is stationary over the terrain.
- Attribute CPU, GPU, physics, terrain, and UI separately. Never disable
shadows, lower authored terrain quality, change BigSpace, or change the
standard substep count to make a graph look better.
In a diagnostics-enabled render host, `lunco-render-bevy` adds
`lunco_shadow_shared_early`/`late` and `lunco_shadow_camera_early`/`late`
timestamps around the native shadow passes. Shared events correspond to
individual point/spot views; camera events include that camera's directional
cascades. Check all four names and their event counts before attributing total
shadow cost. Late spans can contain only timestamp overhead. Use the
early shared child spans `lunco_light_depth/<pass_name>` when attributing
individual maps; native exports prefix them with `lunco_shadow_shared_early/`.
Do not sum child and parent times. `lunco_shadow_view_work` supplies admitted
viewport dimensions, optional phase emptiness and native bin/set counts.
This brief CPU snapshot is not pass execution time; bins are not draw counts
and stable counts do not prove static caster inputs. Native labels identify
current render allocations, not authored lights. Close each child before its
parent. Retain native dependency ordering, native-parameter admission before
begin and render-context buffer order when changing this adapter. Reapply
PBR's system-local early/late
ordering rules after removing the original system; retaining its implicit
type set alone preserves only dependencies targeting that set. Check the
actual shadow image before admitting a capture as performance evidence.
`SharedShadowView` uses the native single-threaded executor for its serial
eight-system GPU chain or two CPU-mode shadow passes. Attribute its inclusive
and self costs separately; frame-level Render and camera Core3d still use
their existing executors. Verify native pass inventory and final buffer order
before comparing executor costs. This render adapter does not change solver
cadence or authoritative simulation ordering.
Unsupported timestamp features or
exhausted per-frame queries leave incomplete GPU evidence, not zero cost.
- For intermittent long frames, export individual CPU zones and correlate them
with perspective/window markers. Exclude screenshot delivery, authored test
verdicts and perspective transitions from settled statistics. Inclusive
render/extraction schedules can contain a native `queue_submit` wait; report
the submission boundary separately from owner computation. A long submission
span alone does not establish its driver, GPU or scheduling cause. Retain
periodic GPU clocks/utilization, CPU pressure and concurrent process evidence,
then run the same exact uninstrumented artifact separately. Failure to reproduce
an earlier tail in a later run does not prove a fix. Record visible popup/UI
state alongside camera and graphics settings.
## Architecture checks
For synchronous USD edit stalls, inspect compound operation count and native
composition lifetime. The document owner's `UsdEditSession` shares one current
authoring stage across an ordered sequence; direct layer changes invalidate it.
Preserve the private candidate and atomic rejection boundary described in
[architecture 21](../../docs/architecture/21-domain-usd.md). Measure the actual
command in a production run; a faster edit still occupies its calling thread.
Also inspect `usd_native_reference_discovery`: native property resyncs prepare
only their asset values, while prim resyncs scan the affected subtree. Asset
types gate provenance and time-sample resolution. Domain live-edit owners consume
one complete notice batch in place; label changes must preserve live child state.
Modelica coupling holds `FixedMain`, while the pacing clock retains running
demand in `Time<Fixed>::overstep`. Compare completed simulation time against
monotonic wall time and inspect pending demand through `SimulationTimingProfile`;
a short native physics service time does not certify realtime co-simulation.
For scene-test diagnostics, `--tick-hz` varies manual update pacing; use the
runtime's `Time<Fixed>` quantum and elapsed time when interpreting physics cost.
Completed Modelica receipts have one reader in `SimulationCompletions`, serviced
before clock projection, before admission of a held pending fixed cycle, and by
the native driver on response readiness between application updates. A ready
receipt can release another cycle in the same update; unfinished work yields
without a wait. Full presentation isolation remains a separate requirement.
The default communication period is one physics tick; longer periods must be
authored explicitly.
For deliberately frozen captures use `StepSimulation` and presentation-timed
sequencing. Manual demand uses the same fixed runner as paced execution and
still respects preparation and solver barriers. A native hold gates the entire
simulation; compare `clock_snapshot().physics_elapsed_s` and `fixed_elapsed_s`
at completed-cycle boundaries before interpreting throughput measurements.
Attribute numerical service separately from transaction dispatch and result
admission. Live workers pass the exact communication point to the existing
`LiveStepper::advance_to` boundary; adaptive Rumoca sessions and fixed
prediction own their internal steps. Preserve the fixed prediction lattice,
event handling, input sampling and finite/completion validation when optimizing
that path. Do not add another worker-side integration grid or catch-up planner.
Keep communication-clock checks at floating point roundoff scale, with finite
timestamps required at both request and completion admission. A solver's state
tolerance must not loosen its communication endpoint validation. Validate the
endpoint using `start + dt`; subtracting large absolute timestamps can reject
a valid short interval through cancellation.
UI exposure publication is paced by `Time<Real>`, independent of simulation
pause and rate. Its dirty-state gate still coalesces unchanged facts. Attribute
main-thread snapshot capture separately from `runtime_ui_policy_preparation`
and owner publication. Native pure policy evaluation uses shared bounded worker
admission, retaining captured hooks and caller context; one job plus one latest
pending snapshot per surface bounds work. Source and identity changes fence
completion. The wasm kernel is currently cooperative, not an isolated worker.
Wait for ready surfaces and inspect preparation failures before taking a UI
performance cohort. This boundary does not isolate the entire fixed runner
from the presentation thread. Keep
mission/timeline waits and telemetry deadlines on their declared simulation
clocks; changing their timers to wall time changes simulation semantics.
For script cost, attribute `rhai_native_task_tick` by stable actor gid and
compare the same task-invocation range or simulation phase. Equal wall-time
windows need not contain the same mission work when realtime pacing differs.
Task callbacks borrow the persistent map through Rhai's bound receiver; see
[the callback contract](../../docs/architecture/rhai-task-tree.md#leaf-callback-contract).
Preserve captures, imports, state/error semantics and fixed cadence while
removing copies at that boundary.
For cost or memory that grows with runtime, check interpreter scope lifetime:
initialized globals persist, while per-call constants and function locals
must be released on both success and error. Use Rhai's scope-rewinding option
at every scenario call boundary; do not periodically clear live scenario state.
For Rhai presentation cost, inspect helper arguments and array iteration for
copies of nested facts. Project the fields a helper consumes before calling
it; indexed access can count participant statuses without copying their model
input/output maps. Preserve the public hook facts and compare complete property
outputs, including empty and unavailable states. Use paired real-owner spans
for attribution; synthetic large-payload timings alone do not establish FPS.
For typed Rhai boundary cost, use the shared `lunco-hooks-rhai` converter.
It borrows input containers; embedding owners lower native leaves through
`dynamic_to_hook_with_native`. Do not build a normalized Dynamic tree before
calling it, clone containers to inspect their type, or add another recursive
converter. Preserve native f64 math, unsigned integers, shared values and
visible rejection of unsupported types. Check the interpreter resource seam
with `typed_conversion_rejects_nested_native_values_without_cloning_them`, then
exercise production typed command/query consumers, including a negative case.
For port-exchange cost, inspect `BindingStatus.connections` and join targets to
`ListPorts` owner metadata. The causal-state sink count is not the number of
compiled wire targets: scene/shader inputs also participate in the exchange.
Separate `cosim_exchange_write` from accumulation before changing routing.
Preserve live metadata, bounds, ownership and stale-slot checks. For shader-name
cost, use the shared borrowed converter described in
[shader parameters](../../docs/architecture/shader-layers-and-params.md);
canonical-name lookup must not allocate, and entities without `ShaderLook` must
reject before conversion. Allocation probes and kernel timings do not certify
whole-scene FPS.
For native physics ordering investigations, enable
`lunco_physics::order_audit=debug` in an owned diagnostic session. The continuous
owner records native body and collider identities, poses, mass/inertia and
velocities, plus contact-graph IDs, colours, manifold indices and prepared
point geometry at the physics clock. Compare the first divergence before
attributing a difference to pool size. This logging is diagnostic and must be
disabled for performance acceptance. Partial pose checkpoints do not prove
full-state replay.
Compound audit rows include native scale and local part mass properties.
If the first divergence is already in COM, compare admitted geometry and
mass ownership before attributing later motion to the query dispatcher.
For continuous-query dispatch, compare the CCD owner's bounded
`minimum_query_batch_size` with its unconstrained zero setting using the same
scene and ordered inputs. Small batches execute the same kernel directly;
larger batches join before authoritative correction. Preserve native query
results and compare complete physics time, including CCD and joints.
The default minimum is eight queries per worker; joined chunks retain prepared order.
Use `continuous_scoped_queries_preserve_order_geometry_and_errors` for bitwise
witness/normal/contact-cache parity before production state replay.
`ccd_query_dispatch` records bounded query and worker counts around the shared
kernel and join. Match query population and simulation phase, retain power
observations throughout each comparison, and separate dispatch duration from
the enclosing sweep and complete physics tick. A changed worker distribution
needs measured benefit in addition to numerical parity.
When attributing native GPU preprocessing, trace allocation identity rather
than only buffer capacity. Bevy's `collect_buffers_for_phase` exchanges
per-phase and frame-level buffer cohorts each frame; equal sizes do not mean
consecutive bindings agree. Native view groups must be present on current
extracted views. Compare actual buffer identities, binding offsets/ranges,
layout descriptors, occlusion textures, work modes/counts and bin-job
parameters, and measure admission overhead and native rebuild frequency.
Pipeline-cache change ticks alone are unsuitable: native queue processing
mutably accesses that resource every frame. Preserve native deferred publication
and every GPU preprocessing/draw pass. See the current handover for the owned
binding-lifetime captures; they establish no product speedup.
For authored image preparation, trace `lunco-materials` typed
`PreparedShaderImage` loading: native decoding and owned RGBA8 filtering precede
source/child publication. CPU filtering awaits the async compute pool with an
owned image, without blocking an I/O worker or borrowing ECS. The renderer resolves `ShaderTexture` and reacts to
source asset events; it must not snapshot resident pixels. The prepared loaders
register no extensions, preserving native image/glTF settings and decoding.
Prepared children use the native render-only extraction contract: pixels move
into GPU preparation while the main asset retains metadata. Audit CPU readers
before choosing that usage; sampler/descriptor edits must come through source
reload with fresh data. Verify initial load and reload publish complete chains, independent color/scalar/
normal identities, native-image forwarding and invalid-pixel rejection at the
asset seam. `load_raster` accepts physical paths; verify labeled requests reject
before issuing a prepared-root load and importer-owned native image handles
still load, bind and reload. Preserve exact RGBA8 transfer, sampler quality and role identity.
Worker-time gains need separate loading/UI/FPS evidence before an app-level claim.
For repeated analytic USD primitives, inspect reflected `Mesh3d` identities
before inferring duplicate preparation or upload cost. `PrimitiveMeshAssets` in
`lunco-usd-bevy-mesh` owns shared preparation and weak native mesh lifetime;
source admission remains in `lunco-usd-bevy`. Preserve the
[immutable mesh contract](../../docs/architecture/render-decoupling.md#immutable-primitive-mesh-assets),
quality replacement and entity-specific edit isolation. Run the authored
`primitive_mesh_sharing.rhai` sandbox gate for equal and unlike dimensions.
Fewer asset IDs alone do not prove fewer GPU draws or faster frames. The retained
`engine.frame_time` series samples raw app-frame values at the fixed 60 Hz
ceiling and may repeat values; collect it before its 240-sample ring truncates
the measurement window. Report it separately from once-per-rendered-frame data.
Search the owning systems for unconditional writes, full-set topology scans,
repeated observer registration, per-frame allocations, polling, and work that
should be gated by a revision/change event. Structural edits should invalidate
structural caches; transform propagation and telemetry output are not by
themselves topology changes. Check both the Builder and View registration paths
before fixing only one.
For loading throughput, compare worker CPU duration with the complete job window
and idle gaps while preparation is queued. `AsyncWorkAdmission` starts work in
PostUpdate and refills released slots on completion; its global bound, priority
service, cancellation and weak queue lifetime remain independent of frame rate.
Verify refill without another host update and retirement with captured permits,
then compare settled terrain readiness and replay the authoritative state.
For physical solar visibility, attribute `publish_sun_visibility` separately
from native physics. Distinguish terrain enclosure cache misses from actual
height evaluations: a warm bounds cache can still repeat procedural samples
at adjacent-cell and refinement endpoints. Ray-local sample reuse must use
exact f64 coordinate bits and preserve traversal, interval budgets, unavailable
data and fault behavior. Run the focused certified-occlusion mechanism checks
and the production terrain solar visibility and invalid-admission gates; compare
the unchanged solar-power observations and run a separate production Twin window.
For procedural synthesis, separate noise, population generation and profile
evaluation. Reuse input-constant preparation at the existing mathematical owner
before adding a population cache. Preserve cell hashes, f64 operation order and
draw independence; compare exact point bits as well as production terrain and
simulation outputs. Keep math diagnostics separate from whole-app acceptance.
For dataset consent, check `publish_dataset_provisioning_surface` separately
from its Rhai policy. Diagnostic-outbox drains must not mark registry catalog
facts changed. Bevy excludes a system's own writes from its next change check;
trace other writers before attributing repeated work to a publication cursor.
Preserve real registry/workspace/command edits, policy replacement and interactive-window
transitions. Run the windowed `dataset_provisioning_surface.rhai` gate with a
declared missing scope; confirm unrelated dismissal preserves the view and
active dismissal clears retired properties without requesting a download.
For the derived scene entity tree, immutable parent insertions use native
lifecycle messages coalesced by entity at the Update gate. Compare current
edge values with the cached ancestry; identical replacements must not rebuild.
Separate change admission from rich candidate reads: the native changed query
returns only entity identities; indexed candidate reads fetch label/visibility
data for those identities. Preserve the candidate predicate and mutable metadata
coverage. Direct mutable component edits must still invalidate the cached tree;
insertion observers alone cannot detect them.
Retain mutable-label and scene-boundary checks, removal handling, unnamed
ancestor invalidation and active-Twin queue retirement. Native renderable
additions cover marker admission; the metadata query also admits new names.
Retain the native mutable metadata change query, including edits to unpublished
worker members. Cover a new name on an already tracked unnamed ancestor.
Compare indexed membership scans with native
change filtering in the live owner before changing the scan strategy. Measure
the complete gate and source observers separately from tree derivation and
panel paint.
The gate exposes `entity_tree_gate_named_changes`,
`entity_tree_gate_removals` and `entity_tree_gate_parent_changes`; compare the
complete gate as well as these phases, with equal instrumentation and cameras.
For frame-contract gate costs, distinguish the full connectivity validator from
its admission/fixed run conditions. The bridge observes native physical and
hierarchy lifecycle events through one change-ticked resource; each consumer
retains its own observation boundary. Preserve insertion, reparenting, removal,
despawn and active-frame switch/removal detection without waking on ordinary
pose values. Validate a disconnected body through the public owner diagnostic
and stopped solver ticks, then verify a replacement scene resumes physics.
For link-sweep costs, attribute `celestial_ephemeris_position` separately from
pair geometry and verdict hooks. Use `link_collect_endpoints`,
`link_snapshot_occlusion_inputs`, `link_evaluate_pair`,
`link_terrain_line_of_sight` and `link_verdict_policy` to distinguish snapshot
preparation, terrain marching and typed-policy marshalling/execution. Pair
spans contain terrain and policy spans; do not add inclusive durations.
The analytic provider's exact-epoch cache also
shares native EMB/Earth VSOP operands across dependent bodies. Preserve native
f64 values and formula order; a new epoch bit pattern invalidates final and
intermediate samples together. Compare public `BodyPosition` results against the
prior exact artifact at adjacent and revisited epochs before claiming a gain.
Before increasing epoch retention, record exact body/epoch keys and cache hits.
Distinguish first evaluations from repeated misses after eviction; extra slots
cannot save unique sample work. Do not quantize epochs or duplicate a maintained
analytical formula to create apparent reuse.
For an exclusive system, check repeated `World::query` construction separately
from iteration. Retain Bevy's native `QueryState` in the owning system when
the query shape is stable; read current membership each pass and collect
identities before structural mutation. Preserve that system's serial schedule
position and lifecycle ordering. A settled-frame saving also needs live
add/remove or replacement evidence, since queries must admit newly matched
archetypes after startup.
For USD Modelica source dispatch, inspect pending membership before attributing
its exclusive span to initialization. Empty calls still flush the World. The
native component/scene-transaction run conditions skip that boundary only when
there is no admissible source work. Verify deferred source insertion, scene
holds and replacement, while retaining the wiring/defaults chain, prim-path
compile order and initialization sampling. A removed idle span proves avoided
work; it does not by itself prove loading or whole-app FPS gains.
The co-simulation endpoint lifecycle publisher uses this native exclusive query
parameter. Validate its same-frame ready transition and run sandbox binding
acceptance again after scene replacement; keep immediate endpoint insertion and
the `PostUpdate` binding boundary intact.
The neutral scenario driver shares its native model query across preparation,
startup, fixed and visualization passes; preserve fresh model/scope/authority
reads and stable actor sorting when changing that owner.
For telemetry retention, separate due recording batches from cheap between-batch
calls. `SignalRegistry::record_scalar_at_rate` admits and appends through one live
history lookup; preserve backwards-time segments, retention, archived-source
reactivation and catalog notifications. A registry benchmark isolates that owner,
but production retention spans and raw physics/frame tails need separate evidence.
Modelica and physics channel-limit checks read the live scalar count after
append and only hash history identity for admission when the catalog is full. Preserve
existing-channel recording above a lowered limit and rejection after history
removal; a cached producer identity alone does not prove that history exists.
For dynamic-body admission, compare `activate_dynamic_bodies` with its native
eligibility gate. Paused or invalid assemblies retain `ShouldBeDynamic` for
diagnostics but must not wake admission when its query has no eligible bodies.
Share the exact archetype filter; retain preview-ancestry checks, stable identity
faults, promotion order and joint holds inside admission. Verify paused poses
and warnings through `sandbox_ramp_placement.rhai`, plus exact-state replay
against the unchanged binary. A stale tracked Modelica reference is not passing
replay evidence; capture a separate baseline and preserve the tracked reference.
For articulated mass facts, separate `refresh_dynamic_joint_island_masses`
from its `dynamic_joint_island_mass_rebuild` span. The physics owner retains
lifecycle invalidation through pauses; native change detection handles mutable
effective masses and joint endpoints. Normal and rollback exchange read the
same derived resource at their existing boundaries. Verify live mass edits,
rejected negative writes and island splitting through `joint_island_mass.rhai`,
plus exact replay against the unchanged artifact. Quiet steps must not rebuild
islands; marker removal, body removal and paused lifecycle edits must still
invalidate them. Preserve native sums and the full-island invalid-mass result.
For a system that queues many compatible ECS component changes, inspect its
`system_commands` flush separately from the system body. Collect changed values
and use the owning crate's existing batch command path where it preserves the
same commit boundary; retain change filtering so a quiet fixed cycle queues
nothing.
In panel paint code, use `PanelCtx::resource` for reads. Its `resource_scope`
temporarily removes and reinserts the resource, which marks it changed even
when the closure only reads it. Scope a mutable borrow only around a real
state transition; otherwise a steady Builder repaint can wake change-detection
systems and full-scene reconciliation on the next Update.
USD authored/composed text painting borrows `UsdViewportState` and its cached
source strings. Check `usd_preview_render_layer_propagation` when diagnosing
preview invalidation; report traversal cost separately from frame time. Opening
several previews must not add bodies, colliders, or joints to the mounted scene.
For SysML requirements rebuilds, inspect `sysml_requirements_rebuild` input
flags. Domain notification publishers check `has_pending_events` before
mutably draining their registry; an empty queue must not invalidate readers.
Workspace document focus and USD editor open/close are not SysML inputs. The
requirements producer compares the active Twin identity, root, manifest, and
file index before reacting to workspace change detection. Verify both an
unrelated editor change (no rebuild) and a Twin/source/evidence change (fresh
projection); do not suppress domain registry invalidation.
Source links use `DocumentRegistry::doc_for_file`, which checks all exact paths
before resolving file aliases. Preserve symlink identity and dirty-document
semantics; do not build a panel-local path registry.
Inspect scenario preparation separately from lifecycle execution. Unchanged
actors borrow their canonical source; only admitted compile/retry work copies
worker inputs. Do not defer initialization or change actor commit order to
reduce this preparation cost.
For Modelica response retention, reuse observable-variable keys and move the
worker's input/output buffers into the accepted record after transaction
validation. Preserve detected-symbol/output precedence and verify reset
isolation, signed-zero values and stale-result rejection at the owner seam.
Modelica workers return current observations only. Retained samples belong to
`lunco-modelica-telemetry` and the shared chunked `SignalRegistry`, installed
through `TelemetryRetentionPlugin`. UI consumers read that same history and
receive only a checked `ModelicaSessionStarted` lifecycle message when a new
session requires binding cleanup. Verify retained history through
`ListTelemetryChannels` and `QueryTelemetryHistory` in both hosts, and exercise
the public accepted-step reader through production. Measure response latency
separately from solver integration and fixed-step output publication.
For loading, separate prepared-FMI lookup/lowering, live construction and ordered
publication. `modelica_live_plan_admission` runs on the command owner;
`modelica_live_construction_job` records queue wait and measures the native session,
metadata and initial-observation children. `modelica_live_construction_commit`
measures publication. Preparation and live sessions use separate captured bounded
worker budgets. Scene and document actors have separate live-owner pools;
each session retains its construction thread through stepping
and retirement. Compare concurrent construction intervals and end-to-end
readiness, not only summed worker time. A round transfers complete input buffers
once, runs independent participants concurrently, and admits checked results in
command order. Require exact replay, terminal observation-failure and scene
replacement evidence before a scheduling gain claim. Preserve exact
communication points, backend numerical profiles, metadata and generation
retirement. The native
compiler already shares its DAE and source map; additional metadata caches do
not address dominant native construction cost.
For mixed loading and live execution, inspect `modelica_live_step_job` queue
wait and execution separately. Match its construction identity and thread to
preparation/construction spans before attributing a response-latency rise to
mailbox blocking; response latency also includes transport and main-thread
admission. Preserve the fixed-tick backlog and barrier state alongside timings.
Modelica and scripted snapshot publication use `ScalarPortMap::upsert_samples`.
The destination retains slot hints, but validates each live layout and exact
name on every copy. Name validation and the bit-exact update share one mutable
slot borrow; measure that copy separately from solver response admission.
`modelica_outputs_copy_variables` isolates the variable-map traversal and port
update; `modelica_outputs_seed_inputs` isolates omitted-input seeding. Both are
children of fixed-step output publication, so compare their total time with
that owner over the same settled window. Their call counts are per participant,
not per simulation tick. The required `ModelicaVariables.values` component owns
the full native f64 reflected snapshot; `ModelicaModel` owns clocks, inputs,
parameters and status. Serial worker admission marks the snapshot changed only
when value bits change. Reflection writes also participate in native detection.
Added models, USD participant markers and destination components force initial
publication. Run the production `modelica_variable_projection` and
`modelica_variables_missing` gates when changing this boundary, plus exact
state replay and lifecycle resource checks for late results and retirement.
Preserve reordering, same-size source replacement, target
edits, clone/clear/compaction retirement and native-bit no-op detection when
changing that mechanism. Do not infer unchanged source topology from map length
or cached iteration order. Preserve the full reflected snapshot and fixed-step
publication boundary, and measure both copying and total owner time; moving work
to another phase is not sufficient evidence of a throughput gain.
For port-write metadata, preserve the live validation boundary. `PortMetadata`
borrows static source/authority text through native `Cow` and owns dynamic text;
check both representations and content equality, then verify public metadata
and collision diagnostics. Borrowing labels must not bypass owner precedence,
stale-handle rejection, writability, bounds or atomic batch admission.
For structural publication, use the existing `PortTopologyState` owner to
observe expensive auxiliary fingerprints by their own component change ticks.
`observe_if_changed` computes a cold key and recomputes changed owners; sample
updates reuse the recorded key. A participant's new admission must refresh
auxiliary facts that could have changed while it was absent. Verify metadata
edits, same-size declaration replacement, removal and re-admission. Keep direct
backend inspection and write validation on the live contract.
For fixed-step port costs, the exchange exposes `cosim_exchange_topology`,
`cosim_exchange_accumulate`,
`cosim_exchange_holds`, `cosim_exchange_write` and `cosim_exchange_diagnostics`
inside the single propagation owner. Attribute these phases before changing
lookup or validation; do not add their nested duration to the parent.
Backend `declare_ports` uses `PortDeclarationQuery`
for both full inspection and exact-name, direction-constrained discovery.
Map-backed owners query the requested name directly; named queries retain only
the first matching direction without constructing owned rows. Preserve the
same declaration order and live metadata checks; topology publication alone
cannot guard an owner edit before its scheduled publication pass.
Avian resolution, named declarations and metadata selection share immutable
name candidates derived from `AVIAN`. Preserve candidate order and live group
membership on removal, re-admission and mobility edits; full inspection retains
table order. The index does not authorize a write or cache world membership.
`write_resolved` shares its locator's `Arc<str>` with canonical input-write
preparation, compares the live owner with its locator, then commits within
the same exclusive World boundary without a name or single-element batch allocation.
Registry clones share the immutable backend table; registration detaches it
without changing existing snapshots or their precedence. Verify snapshot
isolation and shared name identity when changing those allocation boundaries.
Preserve live precedence, metadata, topology revision, slot, value checks, and
rejection ordering. Separately prepared batches still revalidate every write
before committing any of them.
Ownership selection retains the winning backend's optional slot for the same
World borrow. Handle creation, preparation and batch preflight consume that
result without repeating the winner's resolver. Verify one resolver call per
admission, declared owners without a slot, readable input-side sources, stale
layouts and metadata edits; do not substitute a persistent ownership cache.
The shell's steady `WorkbenchSnapshot` check compares borrowed dock and
perspective iterators before materializing owned vectors; preserve that
allocation-free stable path when changing layout publication.
The top-level menu's unique label projection is built only when the menu
registry changes. Width measurement borrows that projection and streams labels
without collecting another vector; compute perspective-tab rows once per UI
pass and reuse them for both width measurement and painting. Do not rebuild the
same responsive menu inputs during steady repaint.
For contributed top-level menus, defer collecting and sorting scripted
contributions until the popup callback runs; a closed menu should only paint its
row and publish its anchor. Use `workbench_custom_menus_render` to inspect that
row path separately from the workbench aggregate.
When a measured UI snapshot builds several indexes from the same entity
population, combine compatible marker reads into the existing query and avoid
another full-population traversal for each marker set. Keep queries over
different populations separate unless measurements show that a broader scan
costs less.
For large Builder hierarchies, derive a lightweight row index from the cached
View on GitHub