Re: [PATCH 0/4] io_uring: improve alloc_cache branch prediction

From: Caleb Sander Mateos

Date: Mon Nov 09 2026 - 18:15:22 EST


On Mon, Nov 9, 2026 at 1:37 PM Jens Axboe <axboe@xxxxxxxxx> wrote:
>
> On 11/3/26 2:10 PM, Caleb Sander Mateos wrote:
> > A call to io_uring_alloc_async_data() that provides a struct io_alloc_cache
> > currently has 2 unnecessary NULL checks in the fast path:
> > - Of the struct io_alloc_cache *, even though it points to a struct io_ring_ctx
> > field
> > - Of the void * entry popped from the cache, even though all cache entries are
> > non-NULL
> > The compiler also incorrectly assumes the success path in io_alloc_cache_get()
> > is the unlikely one because it's written as an early return.
> >
> > Avoid the first NULL check by splitting io_uring_alloc_async_data()'s cache
> > logic to a separate function io_uring_alloc_cached_async_data() that uses the
> > cache unconditionally. Avoid the second by returning a separate success bool
> > from io_cache_alloc() instead of checking the NULL-ness of the returned entry.
> > Also mark io_alloc_cache_get() and io_alloc_cache_put()'s success paths as
> > likely so the compiler can avoid jumps in the fast path.
> >
> > The final commit is a small code simplification in io_futex_wait() noticed while
> > touching the neighboring io_cache_alloc() call.
>
> I hand-applied this, as it needed changes for the post-7.3 trees.
> Patch 3 is somewhat marginal I'd say in terms of rewards for the
> churn, but churn is cheap these days...

Sorry, this was based on io_uring-7.4-20261029, but I guess that
didn't include the dmabuf changes.

Patch 3 removes an impossible branch checking for a NULL entry
returned from the likely(cache->nr_cached) branch in
io_alloc_cache_get(). (I verified significantly shorter codegen in
io_uring_cmd_prep() with no jumps in the fast path after these
patches.) io_uring's whole philosophy seems to be going to great
lengths to micro-optimize the I/O path, so I figured this change was
worthwhile, but feel free to drop it if you feel otherwise :)

I think we could reduce the diff by adding if (!entry) unreachable();
in io_alloc_cache_get() instead. (Or __assume(entry), though that's
only supported on recent compilers.) Would you prefer that?

>
> Anyway, check the end result, please.

The conflict resolution looks good to me.

Thanks,
Caleb