Skip to content

Track timely master: un-shred arrange with multi-capability stamps - #838

Merged
frankmcsherry merged 3 commits into
master-nextfrom
stamps
Aug 19, 2026
Merged

Track timely master: un-shred arrange with multi-capability stamps#838
frankmcsherry merged 3 commits into
master-nextfrom
stamps

Conversation

@frankmcsherry

@frankmcsherry frankmcsherry commented Aug 19, 2026

Copy link
Copy Markdown
Member

Tracks timely master, whose messages are stamped by multisets of timestamps (TimelyDataflow/timely-dataflow#813), and removes the shredding of arranged and reduced batches into per-capability tiles.

Three commits:

  1. Track timely master — the dependency switch (the point of master-next) plus mechanical adaptations: Distributor implementations receive the stamp in place of a time and reproduce it on each produced sub-message, and capture events carry a stamp. All stamps remain singletons; behavior is unchanged.
  2. Un-shred arrange — the retire-capabilities-one-at-a-time tile loop (whose comment read "Until timely dataflow supports multiple capabilities on messages, at least") becomes one batcher.seal(frontier) shipped under a CapabilitySet of the retiring capabilities. For totally ordered times the capability antichain has at most one element and behavior is identical. TraceReplayInstruction's capability hint becomes a Stamp (empty exactly for empty batches); trace import replays under delayed_stamp. Consumers accept multi-stamp batches: join lower-bounds each unit's consolidation meet by the lattice meet of the stamp's elements (it must be the meet — any single element would be unsound for the history advance); reduce, count, threshold, and arrange's own input retain each stamp element.
  3. ReduceTactic retires one batch spanning the interval — the tile abstraction removed from the tactic contract and its implementations. retire returns a single optional batch spanning [lower, upper), shipped stamped with the held times not in advance of the upper limit, which justify its contents. Everything per-tile becomes single-step: one output buffer and builder in the cursor tactics, no per-update reverse routing search in the thinkers, one delta buffer per window in the proxy tactic, and the tile_descriptions machinery is deleted. ProxyReduceBackend keeps its begin/emit/finish lifecycle, but begin takes its one description owned rather than borrowing a list it must clone, emit loses its tile index, and finish yields the batch rather than a vector of them.

Measured on an SCC benchmark with all update rounds concurrently open (single worker, spreads under 1%): 100 nodes / 200 edges / 2,000 rounds runs in 0.88s against 4.06s before the reduce fusion (4.6x); 20 / 40 / 20,000 rounds in 14.2s against 20.6s (1.45x). A separate benchmark probed whether mixed stamps — say {(0, 100), (1, 0)}, whose lattice meet (0, 0) forgoes the consolidation a batch rooted at (0, 100) would seed — cost join anything: no difference against per-capability tiles, to within noise, at tens of millions of updates; the thinker's in-sweep per-key meet advancement recovers the consolidation regardless of the unit's initial meet.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BrUdeCb6dsunVdk4acCPmh

Points the timely dependency at timely master, which stamps each message
with a multiset of timestamps rather than exactly one. The adaptations are
mechanical: Distributor implementations receive the stamp in place of a
time and reproduce it on each produced sub-message, and capture events
carry a stamp. All stamps remain singletons; behavior is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BrUdeCb6dsunVdk4acCPmh
@frankmcsherry
frankmcsherry force-pushed the stamps branch 2 times, most recently from 7a36999 to f6b7ab6 Compare August 19, 2026 13:37
frankmcsherry and others added 2 commits August 19, 2026 09:38
The arrange operator retired capabilities one at a time, carving the batcher
into per-capability tiles because each message could carry only one
capability (its comment: 'Until timely dataflow supports multiple
capabilities on messages, at least'). It now seals one batch per frontier
advance and ships it under a CapabilitySet of the retiring capabilities;
for totally ordered times the capability antichain has at most one element
and behavior is unchanged.

TraceReplayInstruction's capability hint becomes a Stamp (empty exactly for
empty batches), and trace import replays batches under capability sets
minted with delayed_stamp. Consumers accept multi-stamp batches: join
retains the stamp and lower-bounds its unit's consolidation meet by the
lattice meet of the stamp's elements (it must be the meet — any single
element would be unsound for the history advance); reduce, count, threshold,
and arrange's own input retain each stamp element.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BrUdeCb6dsunVdk4acCPmh
The tactic contract required output batches to tile [lower, upper), one per
held capability time, because each message could carry only one capability.
With stamped messages the tiling is unnecessary: retire now returns a single
optional batch spanning the interval, which the driver ships stamped with
the held times not in advance of the upper limit — precisely the times that
justify its contents.

Everything that existed per tile becomes single: the cursor tactics keep one
output buffer and one builder in place of one per held time, and their
thinkers append to a plain vector rather than routing each update through a
reverse search for its covering capability; the proxy tactic accumulates one
delta buffer per window rather than one per held time, and the
tile_descriptions machinery (descriptions, held-time tags, and the tile_of
routing map) is deleted. The ProxyReduceBackend lifecycle keeps its shape —
begin, then windows of corrections and emissions, then finish — but begin
now receives its one description owned rather than borrowing a list it must
clone, emit loses its tile index, and finish yields the batch rather than a
vector of them.

On scc_bench with one worker (spreads under 1%): 100 nodes / 200 edges /
2,000 concurrently open rounds runs in 0.88s against 4.06s before (4.6x);
20 / 40 / 20,000 rounds in 14.2s against 20.6s (1.45x).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BrUdeCb6dsunVdk4acCPmh
@frankmcsherry
frankmcsherry merged commit 7b89903 into master-next Aug 19, 2026
6 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