[REGRESSION] io_uring/rsrc: MSG_RING SEND_FD fixed-file installation slowdown after 7029acd8a950
Chengfeng Lin <[email protected]>
| Newsgroups | dev.linux.lists.regressions,org.kernel.vger.io-uring,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CANGjgdmt0FQ=offsdfn+wEaDxbOFoAa6bi92X_vEo4S6aCZ56A@mail.gmail.com> |
Hi Jens,
I found a repeatable 11.621% slowdown in a narrow fixed-file
registration/update workload at:
7029acd8a950 ("io_uring/rsrc: get rid of per-ring io_rsrc_node list")
The same direction remained with 64 to 4,096 target slots. This is a synthetic
microbenchmark, not an application benchmark or a test of the normal
read/write fast path.
Original patch:
https://lore.kernel.org/io-uring/[email protected]/
#regzbot introduced: 7029acd8a950
#regzbot title: io_uring MSG_RING SEND_FD fixed-file installation slowdown
The source ring has one 4 KiB memfd in fixed-file slot 0. Each round creates a
target ring with an empty 4,096-slot fixed-file table. It then uses
IORING_OP_MSG_RING with IORING_MSG_SEND_FD to fill all target slots in batches
of 64. The timed region includes SQE preparation, io_uring_enter(), and
completion processing. Full per-slot verification and teardown are outside
the timed region.
I used a fresh boot for each point:
e410ffca5886 parent A -> 7029acd8a950 child -> e410ffca5886 parent B
Each point had 3 warm-up rounds and 15 measured rounds. Every measured round
completed 4,096 successful installs. The mean end-to-end cost was:
point mean ns/install
parent A 102.476
child 114.441
parent B 102.576
The child was 11.621% slower than the midpoint of the two parent controls.
Dropping the first measured round from every point gave 11.649%, and the two
parent controls drifted by only 0.097%. All 45 measured rows passed the CQE,
slot-allocation, sentinel, affinity, and unexpected-result checks.
I also repeated the exact-kernel sequence with 64, 256, 1,024, and 4,096
target slots. The child was 11.853%, 8.717%, 8.399%, and 11.889% slower,
respectively. The smaller points were noisier, but all 180 rows passed the
semantic checks. The signal is therefore not confined to 4,096 slots.
The machine was an Intel Core i7-12700KF system with 32 GiB RAM. The process
was pinned to P-core CPU 2. The governor and EPP were set to performance,
Turbo was disabled, and actual runtime preemption was full. The three kernels
used the same normalized config, GCC 15.2.0 toolchain, Kbuild metadata,
module-signing key, equal-length release strings, and workload binary.
An untimed trace also ran 128 successful installs on each kernel. Both points
had 128 calls to io_msg_ring(), io_msg_install_complete(), and
__io_fixed_fd_install(). Calls to io_rsrc_node_alloc() nested under
__io_fixed_fd_install() changed from 0 in the parent to 128 in the child. This
confirms that the workload reaches the new per-install resource-node path; it
does not prove that this one function explains the full timing difference.
The later node-cache change, ed9f3112a8a8 ("io_uring: cache nodes and mapped
buffers"), is already present in Linux 7.1.3. In a separate matched run,
Linux 7.1.3 was still 15.602% slower than the Linux 6.12.95 control midpoint
for the same F0 workload, so the cache did not remove the release-to-release
signal in this test.
I understand that 7029acd8a950 removes per-ring serialization and avoids
resource reclamation stalls, so I am not suggesting a revert. Is this
registration-time cost an expected trade-off, or is the per-install
resource-node setup worth optimizing further?
Evidence bundle:
https://github.com/lcf0399/linux-regression-evidence/tree/37b70f08786d0e2855289cfc317fd97e1160c970/io-uring-msg-ring-send-fd-install
Standalone reproducer:
https://github.com/lcf0399/linux-regression-evidence/tree/37b70f08786d0e2855289cfc317fd97e1160c970/io-uring-msg-ring-send-fd-install/reproducer
Thanks,
Chengfeng