Skip to content

ps-st3: bulk steal transfers, and a test that reaches them - #1

Merged
pathscale merged 6 commits into
mainfrom
feat/ps-st3
Sep 5, 2026
Merged

pathscale merged 6 commits into
mainfrom
feat/ps-st3

Conversation

@pathscale

Copy link
Copy Markdown
Owner

Takes the fork to ps-st3, and carries the two things it exists for.

Upstream PR asynchronics#12, ahead of a release

"Move stolen items with bulk segmented copies." A steal moved items one at a time; this moves them as at most two copy_nonoverlapping runs per ring, since both source and destination can wrap.

Measured on the shape we actually run, one source queue and random victims:

task stock patched
3 µs 28.5 ms 27.3 ms +4.2%
16 µs 133.9 ms 121.0 ms +9.6%

Better than the PR's own claim of 5.5% on lifo, because our shape steals harder.

A differential test, because loom was not testing this code

cargo +nightly miri test is clean on the real bulk path, 355 s. Loom was green on 12 models but on a different implementation: transfer_items had a #[cfg(all(test, st3_loom))] scalar body and a #[cfg(not(all(test, st3_loom)))] bulk body, so every loom model exercised the per-element version and none of them ever ran the code the patch adds.

Closed by compiling the scalar version always as transfer_items_scalar, aliasing it under loom, and sweeping the bulk path against it across every ring capacity in {2, 4, 8, 16, 32}, every start position, and every count.

The test was shown to fail before it was kept:

-    let (lo, hi) = if s <= d { (s, d) } else { (d, s) };
+    let (lo, hi) = (s, d);

cargo test --release --lib
  SIGBUS: access to undefined memory

cargo +nightly miri test --lib
  error: Undefined Behavior: memory access failed: attempting to access
  4 bytes, but got alloc45684+0x8 which is at or beyond the end of the
  allocation of size 8 bytes
     --> src/transfer.rs:111:17
     --> src/transfer.rs:155:9

reverted: test result: ok. 1 passed

The rename

Package is ps-st3; the library is still st3, so use st3::lifo::Worker and the st3_loom cfg need no caller churn.

cargo test --release: 22 + 3 + 1 pass, against 18 + 3 on main. cargo fmt clean. Clippy 7 on this branch, 7 on main.

lxl66566 and others added 5 commits September 5, 2026 21:22
Split both ring ranges at the union of their physical wrap points and move the (at most 3) chunks with ptr::copy_nonoverlapping; small steals keep an inline scalar path, and loom falls back to the tracked per-element loop. Wraparound is exhaustively covered by new bulk steal/self-steal matrix tests.

Signed-off-by: lxl66566 <lxl66566@gmail.com>
The bulk path cannot run under loom, and the reason is legitimate: loom's `UnsafeCell`
exposes no raw pointers, so `copy_nonoverlapping` is inexpressible there. The consequence is
not legitimate. Two implementations of one contract now exist, loom exercises the one that
does not ship, and nothing checks they agree, so a divergence in the bulk version would keep
a green loom run beside it.

The scalar version is now compiled under `test` as well as under loom, named
`transfer_items_scalar`, and `bulk_matches_scalar` runs both over every combination of ring
capacity, start position and count the booking step can produce, wrap points included, and
asserts the destinations are identical.

Planted and reverted, because a check that has never failed has not been shown to work.
Dropping the ordering of the two wrap points, which is wrong exactly when the destination
wraps before the source:

    -    let (lo, hi) = if s <= d { (s, d) } else { (d, s) };
    +    let (lo, hi) = (s, d);

    cargo test --release --lib
      SIGBUS: access to undefined memory

    cargo +nightly miri test --lib
      error: Undefined Behavior: memory access failed: attempting to access 4 bytes,
      but got alloc45684+0x8 which is at or beyond the end of the allocation of size 8 bytes
         --> src/transfer.rs:111:17
         --> src/transfer.rs:155:9

    reverted: test result: ok. 1 passed

Worth recording that the native failure is a memory fault rather than an assertion: a
mis-split chunk reads out of bounds before it can produce a wrong value. So the differential
test detects, and Miri localises. Neither alone gives both.
House convention is a ps- prefix on a forked crate, so the package is
ps-st3. The library keeps the name st3, so `use st3::lifo::Worker` and
the `st3_loom` cfg both work against the fork with no caller churn.
Upstream's workflows were on ubuntu-latest; house runners are ubicloud.
The six jobs it already had (check, test, loom, miri, lints, docs) are
unchanged otherwise.

Release guards on crates.io rather than on a version diff, so a re-run is
a no-op and the first publish of ps-st3 does not need a bump to fire.
@pathscale

Copy link
Copy Markdown
Owner Author

Dropped the core-local bypass slot from this branch. It is parked on experiment/bypass-slot with BYPASS-SLOT.md carrying the measurements and the trigger to look again.

Short version: single-threaded it is +21.9% on a 64-byte payload, but that needs one thread, no contention and no stealing, and it is gone under any of them. Twelve configurations across three loaded harnesses, each against a null of identical code under a second label: nine sit inside their own null, and of the three that clear it one is +3.9%, one +2.8% and one -5.5%. A real effect does not change sign with tile size.

The deciding variable is task duration rather than the slot. It saves roughly one compare_exchange, which is 0.07% of a 2,700 ns task and 3-7% of a 100 ns one, so the trigger to re-measure is tasks under ~700 ns.

What is left here is the part that measured: upstream PR asynchronics#12 at +4.2% at 3 µs and +9.6% at 16 µs on our steal-heavy shape, and the differential test that closes the gap where loom was green against an implementation that was not the shipped one.

Upstream's 0.4.1 plus the bulk segmented steal it has not released, which
measured +4.2% at 3 us and +9.6% at 16 us on our steal-heavy shape.
Patch rather than minor: no API changed, the transfer path got faster.

This commit is last on the branch so the release workflow sees the
version move against its parent when the branch lands.
@pathscale
pathscale merged commit 2f80150 into main Sep 5, 2026
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