Vec::from_slice: build in bulk instead of per-element push_back#1891
Draft
leighmcculloch wants to merge 3 commits into
Draft
Vec::from_slice: build in bulk instead of per-element push_back#1891leighmcculloch wants to merge 3 commits into
leighmcculloch wants to merge 3 commits into
Conversation
`Vec::from_slice` (and `vec!`-from-slice users) built the Vec by calling `vec_push_back` once per element, which is one host call per item and allocates a new intermediate vec object on the host every time. Build the Vec with bulk `vec_new_from_slice` host calls over fixed-size chunks instead. This mirrors the zero-copy improvement made to `BytesN::from` in #1888. Includes a WASM compute-budget bench (`tests/bench_from_slice`) comparing `Vec::from_slice` against `Vec::from_array` (already bulk) and a baseline, plus a unit test covering empty, sub-chunk, exact-chunk-multiple and cross-chunk lengths. https://claude.ai/code/session_0168wkXopix1LPcuzi6AS4WF
Contributor
There was a problem hiding this comment.
Pull request overview
This PR optimizes soroban_sdk::Vec::from_slice by replacing per-element vec_push_back host calls with chunked bulk vec_new_from_slice calls, reducing host-call overhead and intermediate host allocations. It also adds a small unit test to validate correctness across chunk boundaries and introduces an ignored WASM compute-budget benchmark (plus its contract) to measure the improvement.
Changes:
- Reworked
Vec::from_sliceto build via fixed-size chunk buffering +vec_new_from_slice, then combine chunks withvec_append. - Added unit test coverage for empty/sub-chunk/exact-multiple/cross-chunk lengths.
- Added a new
tests/bench_from_slicecontract crate and an ignored SDK-side benchmark harness to report CPU/memory budget costs.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
soroban-sdk/src/vec.rs |
Implements chunked bulk construction for Vec::from_slice and adds a correctness unit test. |
soroban-sdk/src/tests/bench_from_slice_wasm.rs |
Adds ignored compute-budget benchmarks that call into the new bench contract WASM. |
soroban-sdk/src/tests.rs |
Registers the new benchmark module in the SDK test suite. |
tests/bench_from_slice/src/lib.rs |
Adds the bench contract exposing baseline/from_slice/from_array entrypoints. |
tests/bench_from_slice/Cargo.toml |
Defines the new bench contract crate and its SDK feature configuration. |
Cargo.lock |
Adds the new test_bench_from_slice workspace package to the lockfile. |
Follow the #1888 precedent of keeping the benchmark in the PR description rather than committing a bench crate (which would require committed cargo-expand output and trips fmt/docs/expand-test-wasms CI). Also wrap the long vec_new_from_slice lines to satisfy rustfmt. https://claude.ai/code/session_0168wkXopix1LPcuzi6AS4WF
from_slice converts each element by reference into a Val (like from_array) and no longer clones, so the T: Clone bound is removed.
This was referenced Jun 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Vec::from_slicepreviously built the Vec by callingvec_push_backonceper element. Each call is a host call that also allocates a new intermediate
vec object on the host. This change builds the Vec with bulk
vec_new_from_slicehost calls over fixed-size chunks instead.Why
This is the same class of inefficiency that was fixed for
BytesN::fromin#1888 (per-element host calls where a bulk host op exists), found by sweeping
the SDK for element-by-element host-call patterns.
Net cost (baseline subtracted), measured on the guest budget with a WASM
compute-budget bench built the same way as the #1888 bench (
baseline_*twinsubtracted;
from_arrayshown as the already-bulk reference):vec_from_slice_32vec_from_slice_96vec_from_slice_192For reference, the already-bulk
vec_from_array_192net cost is 171,517 CPU /1,656 mem, so after this change
from_sliceis on par with (here, even below)the bulk constructor.
Bench contract and harness
Contract (one
test_*cdylib crate):Harness (in
soroban-sdk/src/tests,#[ignore]d):Run with
make build-test-wasmsthencargo test --release -p soroban-sdk --lib --features testutils -- --ignored --nocapture.Notes
The chunked approach uses a fixed-size stack buffer of
Vals, so it works inno_stdwithoutalloc(the common contract case). A unit test(
test_vec_from_slice_chunking) covers empty, sub-chunk, exact-chunk-multipleand cross-chunk lengths.
Following the precedent of #1888, only the fix + correctness unit test are
committed here; the bench lives in this description rather than in the tree.
One of three related findings from sweeping the SDK for per-element host-call
patterns (see also:
Vec::extend_from_slice#1892,Vec::from_iter).