Skip to content

Finish a wide aggregation on the pool - #771

Merged
tamnd merged 4 commits into
mainfrom
px-merge
Aug 25, 2026
Merged

tamnd merged 4 commits into
mainfrom
px-merge

Conversation

@tamnd

@tamnd tamnd commented Aug 25, 2026 •

Copy link
Copy Markdown
Owner

Follow on to #766, same query and same measurement. After that change the 100k group aggregation at eight workers spends its time as roughly 37 ms of parallel scan and 20 of serial tail, and the tail is two things: folding the eight workers' group tables into one, and building the answer rows out of the folded table.

Both are parallel work being done on one thread while the pool sits idle, and both are here.

The fold went pairwise up a tree. Every worker sees keys from all over the scan, because that is what the morsel scheduler is for, so each partial ends up about as wide as the answer and every fold is a full width merge. Folding eight of them into the first is seven of those one after another. The tree does the same seven merges in three rounds, each round on the pool. An odd table carries to the next round rather than joining a pair, so every merge in a round is the same size, and this thread takes one pair itself the way worker zero takes morsels.

The row build went to slices of the settled order. Once the order is decided the groups are independent, so a hand takes a slice and decodes it into finished rows. It reads the accumulators out of the table rather than moving them away first, which an accumulator being Copy makes free, and that is what lets the slices share the table.

Hands are per worker that ran, not per core. A query asked for on one thread has to be answered on one thread, tail included, or the per core floors in budgets.toml stop measuring a core. Under four thousand groups a hand it stays on this thread, because a latch and a lock per hand cost more than the decoding they would split.

There is a test that a table wide enough to take the split answers exactly what the same table answers on one hand, in the same order, since the split is a split of the work and not of the answer.

Measured on gamingpc, which was quiet, medians of six paired alternating runs of two separately built binaries. The hundred thousand group query went 40.8 ms to 33.9 at eight workers, 243 to 296 M rows/s, and the branch was faster in all six pairs. At one worker it read 99.5 against 99.4, which is the check that the hand count follows the run and not the machine. The twelve group shape and the thousand group string shape did not move, the first because it has no tail and the second because a thousand groups is under the split. That shape scales 2.9x from one worker to eight now, against 2.4x before.

Part of P2, zu#75.

tamnd added 4 commits August 25, 2026 14:48
Every worker sees keys from all over the scan, so each partial ends up
about as wide as the answer and folding eight of them into the first is
seven full width merges one after another, at the point in the query
where nothing else is running. On the hundred thousand group bench that
is 8 to 18 ms of a 65 ms query.

Same seven merges, three rounds, each round on the pool the scan has
just finished with. An odd table carries to the next round rather than
joining a pair, so every merge in a round is the same size, and this
thread takes one pair itself the way worker zero does on the scan.
The rows of a wide aggregation were built one after another on the
thread that finished the run, and that is 7 to 17 ms of a 65 ms query
at eight workers. Decoding is per group and the groups are settled once
the order is, so slices of the order are independent work and the pool
the scan just finished with is sitting idle.

One hand per worker that ran, not one per core: a query asked for on
one thread is answered on one thread, tail included, or the per core
numbers in budgets.toml stop meaning what they say. Under four thousand
groups a hand it stays on this thread, since a latch and a lock per
hand cost more than the decoding they would split.
Bounded list entities from #770, which merged without them.
@tamnd
tamnd merged commit ee0eef9 into main Aug 25, 2026
40 checks passed
@tamnd
tamnd deleted the px-merge branch August 25, 2026 08:49
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