Skip to content

ArrayRef::new: encode the fill once; allocate array bodies fallibly - #9

Merged
somdoron merged 1 commit into
mainfrom
array-new-encode-fill-once
Oct 13, 2026
Merged

somdoron merged 1 commit into
mainfrom
array-new-encode-fill-once

Conversation

@somdoron

Copy link
Copy Markdown
Contributor

Problem

submilli builds large strings by allocating an empty $rawString (mutable i16 GC array) with ArrayRef::new(.., &Val::I32(0), len) and filling it with write_i16 (SUB-1668). That path:

  1. type-checked and encoded the same fill Val once per element, on top of a zero-fill — ~64M wasted ops for a 32Mi-unit string;
  2. used vec![0u8; byte_len], which aborts the process on allocation failure even after the limiter admitted the bytes. i16_body (flat_map().collect(), grows by doubling) and the i8 to_vec() paths had the same issue.

Change

  • ArrayRef::new checks the fill once, reserves through the limiter, encodes it once into a stride-sized pattern, and replicates it. An all-zero pattern is just one zeroed allocation. (Null refs encode non-zero, so they take the copy path.)
  • All array body builders allocate via try_reserve_exact: alloc (new_fixed) uses zeroed_body, i8 paths use copied_body, i16/i64 share a generic le_body.
  • Shared body_len/check_elem helpers. Minor behaviour change: new_fixed now rejects more than u32::MAX elements.

Tests (tests/gc_host.rs)

  • Non-zero packed i16 fill (0x5_1234 → 0x1234), non-null anyref fill, and null fill.
  • Limiter refusal on ArrayRef::new before any body exists.
  • new_from_i8_slice/new_from_i16_slice with u32::MAX + 1 elements error before copying (64-bit only; inputs are lazily-mapped zero pages).

cargo clippy --all-targets -- -D warnings and cargo test (with and without --features async) pass.

🤖 Generated with Claude Code

ArrayRef::new type-checked and encoded the same fill Val once per element
after zero-filling the body, so allocating a large array to overwrite in
place (submilli's $rawString, SUB-1668) did ~2 ops per element of waste.
It now checks and encodes the fill once and replicates it; an all-zero
fill is a single zeroed allocation.

Array body builders (alloc, the i8 to_vec paths, i16_body) used
infallible allocation that aborts the process even after the limiter
admitted the bytes. All now go through try_reserve_exact; i16/i64 share
one le_body.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@somdoron
somdoron merged commit 88788e7 into main Oct 13, 2026
10 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.

1 participant