Repository navigation
Don't drop the write segment's pages on every take at its end - #2486
Conversation
|
No issues found. |
select_next_read_segment started with madvise(MADV_DONTNEED) over the read segment and only then looked for a segment after it. A consumer that has caught up with the publisher reads the segment being written, so every take at its end dropped that segment's pages (four syscalls for an 8 MB segment) and the publisher's next write faulted them back in. A single worker thread rarely gets there mid-batch, but with the consumers on other threads it happens on nearly every take. Return early when the read segment is the write segment, and only drop the pages of a segment that is actually left behind. Measured on an i9-13900H with the broker on 4 P-cores and --workers=4 (the multi-threaded branch), 16-byte messages, AC power: one queue with 1 publisher and 8 consumers went from 442k to about 875k msg/s (1 worker: 1.14M; main: 1.12M), with 1 consumer from 918k to 1.17M, and the fan-in case (8 publishers, 1 consumer) from 1.00M to 1.16M consumed. perf had madvise at 2.6% of the broker's cycles before, and the consumers parking on the store lock behind it. (cherry picked from commit 6efa899)
8d6df40 to
8435d5d
Compare
|
@kickster97 @weistrand i'm thinking this might be a RC bug fix too? It's a two line change, to fix a huge performance regression. |
Will merge this but don't think it actually improves anything right now? Only improves for a multi-threading scenario and we don't have that in this path? I rewrote the changelog a bit. |
@weistrand Why do you think it only applies in MT? |
Basically what is written in the PR description "On a single thread a consumer rarely gets there mid-batch" π But doesn't improve at all is maybe a too strong statement. So it's probably good that we got this in π |
select_next_read_segmentstarted withmadvise(MADV_DONTNEED)over the read segment and only then looked for a segment after it. A consumer that has caught up with the publisher reads the segment being written, so every take at its end dropped that segment's pages (four syscalls for an 8 MB segment) and the publisher's next write faulted them back in. On a single thread a consumer rarely gets there mid-batch; with the consumers on other threads (the--workersstack) it happens on nearly every take.The fix returns early when the read segment is the write segment, and only drops the pages of a segment that is actually left behind.
Found with
perf record --call-graph dwarfon the multi-threaded branch:madvisewas 2.6% of the broker's user cycles, all from this call, with the consumers parked on the store lock behind it. Measured there (i9-13900H, broker on 4 P-cores,--workers=4, 16-byte messages, median of 3 runs on AC power):Single-threaded cells are unchanged (1.14M on the hot queue, 2,9xx cycles/msg). There is no spec: the only observable effect is a syscall count, and purge, delete and the segment switch itself go through the unchanged branch.