Skip to content

chore: release v2.2.4 - #45

Merged
Ttimmahlax merged 2 commits into
mainfrom
release-plz-2026-10-05T01-18-42Z
Oct 8, 2026
Merged

Ttimmahlax merged 2 commits into
mainfrom
release-plz-2026-10-05T01-18-42Z

Conversation

@github-actions

@github-actions github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

🤖 New release

  • rusty_alloc: 2.2.3 -> 3.0.0 (⚠ API breaking changes)
  • rusty_alloc-api: 2.2.3 -> 3.0.0

⚠ rusty_alloc breaking changes

--- failure constructible_struct_adds_field: externally-constructible struct adds field ---

Description:
A pub struct constructible with a struct literal has a new pub field. Existing struct literals must be updated to include the new field.
        ref: https://doc.rust-lang.org/reference/expressions/struct-expr.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/constructible_struct_adds_field.ron

Failed in:
  field Heap.large_cache in /tmp/.tmpt1r4st/rusty_alloc/crates/rusty_alloc/src/heap.rs:187
  field Heap.large_freed in /tmp/.tmpt1r4st/rusty_alloc/crates/rusty_alloc/src/heap.rs:193
  field Heap.deferred_due in /tmp/.tmpt1r4st/rusty_alloc/crates/rusty_alloc/src/heap.rs:214
Changelog

rusty_alloc

3.0.0 - 2026-10-08

Fixed

  • (alloc) fire the deferred-free hook with no &mut Heap alive
  • (heap) stranded large spans after adoption; perf: segment scrub, large cache

Fixed

  • Freed model memory no longer stays stranded after a loader thread
    exits.
    A thread that exits abandons its segments with their blocks live;
    blocks freed into them later are collected when another thread adopts the
    segment, but adoption retired only ONE dead large span per segment and left
    the rest carved for the life of the process. A model loaded on one thread
    and dropped on another kept ~0.6 of its size resident and unreusable,
    whatever purge_delay said. Every dead large span is now retired. Adoption
    also no longer releases the empty segment it has just parked (which left
    the heap releasing every empty segment instead of keeping one).

  • A freed huge block (> 32 MiB) is purged when purging is on. It used to
    rejoin the arena resident whatever purge_delay said: a dead Whisper-small
    embedding (152 MiB) stayed resident for the life of the process. Details,
    measurements and the consumer report: docs/plans/huge-free-retention.md.

  • A deferred-free hook that allocates is no longer undefined behaviour.
    mi_register_deferred_free's hook fired inside the generic allocation
    path while that path held &mut Heap, so a hook that allocated (or freed)
    re-entered the heap under a protected exclusive borrow. Miri reported it
    (Stacked Borrows, tests/openheimer.rs), and it had kept the miri CI job
    red since 2.2.3. The hook now fires at the next allocation entry, before
    any &mut Heap exists. Cost: one flag test per slow-path entry (perl and
    sqlite allocator instructions +0.16 % / +0.22 %).

Performance

  • Recycled segments are no longer scrubbed whole. Every thread's first
    segment and every huge allocation zeroed the 45 KB header of a recycled
    chunk; now only the owner table and the slots read before a carve are
    zeroed, and a slot is zeroed at its first carve. Huge segments also skip
    511 unused slot writes and scan one slot, not 511, when freed. Measured
    (callgrind, memset counted as real instructions): 64 MiB malloc+free
    8,959 -> 824 Ir (-90.8 %), a thread's life -12.4 %, a Rust thread-pool
    workload -15.0 %.
  • A freed large block (<= 4 MiB) is kept for same-size reuse while
    purging is off, and only when it is a lone free (never the end of a
    teardown run, so a model swap lays out exactly as before). A 2 MiB
    malloc/free pair 293 -> 138 Ir.
  • Multi-chunk arena claims read each bitmap word once and claim a
    one-word run with one atomic: 6 -> 2 locked read-modify-writes per huge
    allocation.

Every opscan op is unchanged or better; perl, sqlite and Endless Sky are flat
on allocator instructions; code size +361 bytes gzipped on wasm.

rusty_alloc-api

2.2.1 - 2026-09-25

Performance

  • GlobalAlloc methods are #[inline], as the mimalloc crate's are, so
    rustc's __rust_alloc / __rust_dealloc shims carry the fast path instead
    of jumping to it, and dealloc is the free fast path with its null test
    folded away. Measured whole-program against 2.2.0 on two deterministic Rust
    workloads (bench/rust-globalalloc.sh): -21.1 % and -5.8 %.
  • Layouts aligned up to two words (16 bytes on 64-bit) come from the natural
    size classes
    , which are already aligned that far, instead of the aligned
    path; every hashbrown table is such a layout. tests/natural_align.rs pins
    the alignment for every size class through alloc, alloc_zeroed and realloc.
  • realloc keeps a block in place at any alignment when it fits instead
    of always allocating, copying and freeing above 8 bytes of alignment:
    -27.3 % on an over-aligned buffer workload.


This PR was generated with release-plz.

@github-actions
github-actions Bot force-pushed the release-plz-2026-10-05T01-18-42Z branch from 8293870 to 6bd7a5d Compare October 8, 2026 01:26
@github-actions github-actions Bot changed the title chore: release v2.2.3 chore: release v3.0.0 Oct 8, 2026
…a semver note

cargo-semver-checks flags Heap's three new pub fields
(constructible_struct_adds_field). Shipped as 2.2.4 by the maintainer's
decision; the release notes open with the note.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Ttimmahlax Ttimmahlax changed the title chore: release v3.0.0 chore: release v2.2.4 Oct 8, 2026
@Ttimmahlax
Ttimmahlax merged commit 86bcabe into main Oct 8, 2026
13 checks passed
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.

2 participants