Re: [linus:master] [fs/pipe] f7f4665dc5: lmbench3.PIPE.bandwidth.MB/sec 18.5% regression

From: Breno Leitao

Date: Fri Nov 06 2026 - 06:13:24 EST


On Thu, Nov 05, 2026 at 04:57:33PM +0100, Mateusz Guzik wrote:
> On Thu, Nov 5, 2026 at 4:28 PM Breno Leitao <leitao@xxxxxxxxxx> wrote:
>
> The test at hand has multiple readers and writers using the same pipe,
> with 64KB i/os.
>
> Prior to the patch each writer had its own private pool to draw from,
> guaranteeing no allocation will happen under the mutex.
>
> With the patch the reader exit also drains the pool.
>
> As a result tons of allocation ends up happening under the lock again:
>
> - 94.88% 94.88% bw_pipe [kernel.kallsyms] [k]
> __alloc_frozen_pages_noprof
> 94.88% __internal_syscall_cancel
> entry_SYSCALL_64_after_hwframe
> do_syscall_64
> ksys_write
> vfs_write
> - anon_pipe_write
> - 47.46% alloc_pages_noprof
> alloc_pages_mpol
> __alloc_frozen_pages_noprof
> - 47.42% anon_pipe_prefill_and_lock
> alloc_pages_noprof
> alloc_pages_mpol
> __alloc_frozen_pages_noprof

Ack, this matches what I found as well. Thanks for investigating it.

Because the preallocated pages are not private to the writer anymore,
the reader flushes them while the writer waits for room in the pipe,
and the writer then has to allocate them inside the lock.

This basically loses the wins[0] from commit 212ed884a1aeef ("fs/pipe:
pre-allocate pages outside pipe->mutex in anon_pipe_write") for this
specific scenario.

> I don't think multiple high-volume writers vs multiple high
> volume-readers is a realistic scenario and I would not bother fixing
> it.

Agree, but I would like to spend some cycles on it.

> However, should someone want to address it, I think the patch should
> be reverted and the resulting state tweaked. The patch at hand came
> after the mutex is released -- the kernel prior to any of this would
> still put_page on the reader side under the lock. This bit would have
> to get tweaked to recover the loss in that scenario (not to be
> confused with the loss reported here).

We can revert the patch, but that would bring back the two page pools
(the on-stack prealloc and tmp_page[]), which is probably worse than
this regression itself (IIRC it would also lose the gains for smaller
writes (about 20% for 8-16 KiB writes IIRC ))

That said, these are the items I am planning to spend some time one:

1) Reclaiming the pooled pages from a shrinker, as suggested in [1]

2) Trimming the pool gradually on the reader side, instead of cutting it
down to two pages in one go. Or not trimming it while a writer is
in the waiting room (!?)

3) Keeping the writer's preallocated pages private again, while keeping
the unified pool (i.e. without bringing tmp_page[] back).

4) Freeing the pages the reader drops after releasing pipe->mutex,
instead of under it, as you suggested. This is independent of the
options above.

5) Longer term: copying the data into the preallocated pages before
taking pipe->mutex, so the writer only links them into the pipe
under the lock. This doesn't seem trivial, but it would make this
whole pre-allocated buffers go away

6) Any other idea?

[0] https://lore.kernel.org/all/202607091015.c3936260-lkp@xxxxxxxxx/
[1] https://lore.kernel.org/all/CAGudoHGKyN6k+eSAUm35_WDSZcxxtm4QL6fO+4rYJTvtObMqzA@xxxxxxxxxxxxxx/

Thanks for looking at it,
--breno