Skip to content

Dynamics consumer memory growth exceeds the existing flatness limit before next release #1623

Closed

Description

@InauguralPhysicist

The next-release consumer wave fails dynamics' existing memory-flatness check against EigenScript candidate 96bbbb543fdbfe01e809eee09e7c67986085ed1d. Dynamics source is merged 52dd7d200ae1ac04dd33cdeb3e0a976af8343567. Mouse interaction checks now pass; this is separate from dynamics#47's wrapper ownership repair.

The unchanged gate allows at most 25,600 KB growth between its cold-process endpoints and an absolute peak of 204,800 KB. The wave observed static growth 45,952 KB and toggle growth 35,200 KB, failing flatness while remaining below the absolute ceiling.

A bounded diagnostic using the unchanged tests/bif_ui.eigs, direct owning binaries, static mode and requested BIF_TICKS 30/300 produced:

Runtime Execution policy Peak RSS at 30 / 300 (KB) Growth (KB)
Published pin, a6c50fb Default 140544 / 162304 21760
Published pin, a6c50fb Forced VM 140544 / 161792 21248
Candidate 96bbbb5 Default 147200 / 193280 46080
Candidate 96bbbb5 Forced VM 146304 / 192640 46336

All eight calls exited 0 with empty stderr, exact existing work counters (1 build, 1 series, 4000 points, 4 markers), and full stdout matching within each runtime. Source/binary identities and process cleanup were independently audited. The excess persists without default JIT or the counting wrapper. These are requested tick budgets, not independently measured rendered-frame counts. One cold pair per condition does not establish repeatability, an unbounded leak, or allocation attribution. The pin/current reports differ at two observer flags; no cross-version semantic equivalence is claimed.

Done when:

  • Attribute the increased peak growth to a source interval and mechanism using bounded ordinary measurements.
  • Repair the responsible implementation while retaining the existing workload and acceptance thresholds.
  • Pass the normal dynamics memory gate, including its middle endpoint and toggle arm, and the complete consumer wave on the final candidate.
  • Preserve the failing observations and verify owning runtime profiles, actual work and process cleanup.

Local evidence: release-blockers-20261003/1590-consumer-96-wave2-logs/run.ruYNUy/dynamics.log, dynamics-memory-eight-v3/, and critic-dynamics-memory-eight-v3.md. Runtime PR #1616 remains draft pending acceptance. No release cut is authorized.

Activity

  1. github-actions commented on Oct 4, 2026

    @github-actions

    Thanks for filing. Labelled needs-triage because it has no area: label yet. The scheme is area:<subsystem> (runtime-vm, jit, concurrency, observer, memory, trace-tape, packages, http, gfx, embed, docs, ci, gates, lint-tooling, consumer, aot, stdlib) plus a kind (kind:*, or the stock bug/enhancement) — add the ones that fit if you know them, and a maintainer will confirm and drop needs-triage. See CONTRIBUTING.md, "Reporting Bugs".

  2. added
    bugSomething isn't working
    and removed
    needs-triageFiled without an area: label; triage and label it
    on Oct 6, 2026
  3. InauguralPhysicist commented on Oct 6, 2026

    @InauguralPhysicist
    CollaboratorAuthor

    Consumer-wave re-run on a candidate containing #1629: memory gate PASSES

    Candidate: v0.44.0 = 01bbf7ea843e04aa779199a105cdc0802271c241. This is also current main: git rev-list --count v0.44.0..origin/main = 0. dynamics pins the same tag: dynamics#49 merged as f20a0a5 and sets .devcontainer/Dockerfile EIGS_REF=v0.44.0.

    Containment:

    $ git merge-base --is-ancestor 45a71e1d 01bbf7ea && echo CONTAINS
    CONTAINS
    

    (45a71e1d is the merge commit of #1629, "gc: retire sole-pin candidates between full cycle scans".)

    The original wave measured 96bbbb54, a stale pre-rebase head of the #1616 branch that doesn't contain #1629. It was the wrong candidate.

    Method (mirrors runtime's bisect measurements)

    • Fresh clone at 01bbf7ea, make gfx CC=gcc. That's the same build as the dynamics devcontainer.
    • dynamics at main f20a0a5, clean tree. tests/test_bif_mem.sh was not modified: sha256 f789ca14…, GROWTH_KB=25600, CEILING_KB=204800, VCAP=1500000.
    • Same setup as CI and runtime's runs: DISPLAY unset, so the gate uses xvfb-run -a, and every process pinned to 4 CPUs with taskset -c 0-3. A GitHub runner has 4 vCPUs. Every leg is a cold process: GNU time %M peak RSS under ulimit -v 1500000.
    • A: 8 full runs of the unchanged gate. Each run measures static and toggle at 30/100/300 frames, and growth is peak(300) − peak(30). Each run also includes both planted faults.
    • B: 6 interleaved cold pairs (30 vs 300 frames) per cell, for static/toggle × default/forced-VM (EIGS_JIT_OFF=1). These use runtime's unchanged measure.sh / run_pairs.sh method, with the order rotated each round.
    • Control: runtime's 96bbbb54 build ran through the same unchanged gate, interleaved at rounds 2, 5 and 8. This shows the instrument still catches the regression on this box today.

    A. Unchanged gate, 8 runs on v0.44.0 (KB; peaks at 30 / 100 / 300 frames)

    run static peaks static growth toggle peaks toggle growth exit planted faults caught
    1 128,676 / 132,048 / 132,308 3,632 128,492 / 130,944 / 132,596 4,104 0 both
    2 129,428 / 131,160 / 132,692 3,264 127,968 / 130,696 / 131,748 3,780 0 both
    3 129,216 / 132,424 / 132,992 3,776 127,872 / 130,028 / 131,256 3,384 0 both
    4 129,144 / 131,132 / 131,656 2,512 128,628 / 130,332 / 132,316 3,688 0 both
    5 129,028 / 130,924 / 132,416 3,388 128,584 / 130,644 / 132,872 4,288 0 both
    6 129,584 / 131,868 / 131,788 2,204 128,552 / 130,512 / 131,944 3,392 0 both
    7 129,072 / 131,852 / 132,544 3,472 128,656 / 130,788 / 132,444 3,788 0 both
    8 128,884 / 131,792 / 132,100 3,216 128,804 / 131,572 / 131,852 3,048 0 both
    min / median / max 2,204 / 3,326 / 3,776 3,048 / 3,734 / 4,288 8/8 PASS

    Limit is 25,600 KB, so the worst run is under 17% of it. The highest peak in any leg was 132,992 KB, against the 204,800 KB ceiling. Structure counters held in every leg (built=1, series=1, points=4000, markers=4).

    Control: stale 96bbbb54, same gate, same box, same session:

    run static growth toggle growth exit
    ctrl2 46,692 34,580 1 (FAIL)
    ctrl5 46,592 35,704 1 (FAIL)
    ctrl8 46,440 35,644 1 (FAIL)

    This matches the wave's 45,952 / 35,200 and runtime's 6 of 6 cold-pair failures.

    B. Cold pairs, v0.44.0: peak RSS at 30 → 300 frames = growth (KB)

    round static, default static, forced VM toggle, default toggle, forced VM
    1 128,800 → 131,520 = 2,720 129,160 → 132,196 = 3,036 127,852 → 132,128 = 4,276 128,080 → 131,728 = 3,648
    2 129,232 → 131,716 = 2,484 129,656 → 131,212 = 1,556 127,904 → 132,624 = 4,720 128,880 → 131,908 = 3,028
    3 128,900 → 132,084 = 3,184 128,876 → 132,308 = 3,432 128,292 → 132,864 = 4,572 128,208 → 131,644 = 3,436
    4 128,780 → 132,316 = 3,536 129,824 → 132,484 = 2,660 129,040 → 132,064 = 3,024 127,172 → 131,804 = 4,632
    5 128,668 → 132,248 = 3,580 129,104 → 131,904 = 2,800 128,316 → 131,844 = 3,528 128,332 → 131,844 = 3,512
    6 129,012 → 132,312 = 3,300 129,000 → 132,140 = 3,140 128,632 → 131,980 = 3,348 127,580 → 132,084 = 4,504
    min / med / max 2,484 / 3,242 / 3,580 1,556 / 2,918 / 3,432 3,024 / 3,902 / 4,720 3,028 / 3,580 / 4,632

    0 of 24 pairs went over 25,600 KB. All 48 processes exited 0 with empty stderr, BIF-UI-OK, and the exact work counters.

    Full dynamics suite on v0.44.0 (CI order, same setup)

    test_lint, test_smoke, test_lab, test_orbit_hist, test_bifurcation, test_orbit_oracle, test_orbit_mouse (16 checks, all three planted faults caught) and test_bif_mem: 8/8 PASS.

    Independent check: dynamics main CI on the v0.44.0 pin (run 37298446691, push, f20a0a5) is green. Its gate logged static growth 1,288 KB and toggle growth 2,016 KB.

    Environment note (not a #1623 issue)

    On this 8-CPU box, running with all 8 CPUs visible makes any build abort with eigenscript: out of memory (requested 80 bytes) under the gate's ulimit -v 1500000. That happens on v0.44.0 too, and the gate then reports rc=134 FAIL. With 7 or fewer CPUs it runs. The likely cause is per-thread address-space reservation in the software renderer. Runtime's runs and this one were pinned to 4 CPUs, the same as a GitHub runner. This is a dynamics gate portability caveat and doesn't affect this verdict.

    Verdict

    PASS. On a candidate containing #1629, the unchanged dynamics memory gate passes 8 of 8 runs, middle endpoint and toggle arm included. All 24 cold pairs (static and toggle, default and forced-VM) are at least 5× under the 25,600 KB flatness limit. The stale 96bbbb54 still fails on the same box. The full dynamics suite passes. Closing as fixed by #1629 (45a71e1d, shipped in v0.44.0).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:memorySubsystem: memorybugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions