Skip to content

Remove unecessary heap allocations when processing Epoll events#612

Open
mtjhrc wants to merge 3 commits intocontainers:mainfrom
mtjhrc:dont-alloc-epoll-events
Open

Remove unecessary heap allocations when processing Epoll events#612
mtjhrc wants to merge 3 commits intocontainers:mainfrom
mtjhrc:dont-alloc-epoll-events

Conversation

@mtjhrc
Copy link
Copy Markdown
Collaborator

@mtjhrc mtjhrc commented Apr 1, 2026

This removes unecessary heap allocations during event loop processing.

This definitely shows up in a profiler on macOS significantly (I was looking at virtio-net), though the high variance between runs makes it hard to measure a concrete improvement. Either way, it's easy to avoid the unnecessary work.

This allows for platform-specific optimizations that need mutable access
to internal buffers during wait. Since Epoll is Clone, callers that
need to call wait from separate contexts can use a clone.

Update all call sites to use `let mut epoll` / `fn work(mut self)`.

Signed-off-by: Matej Hrica <mhrica@redhat.com>
@mtjhrc
Copy link
Copy Markdown
Collaborator Author

mtjhrc commented Apr 1, 2026

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request optimizes the event loops in various virtio workers by moving event vector allocations outside of the main loops and updating the Epoll::wait method to require mutable access. The macOS implementation of Epoll was refactored to reuse an internal buffer, reducing per-call allocation overhead. A high-severity issue was identified in the macOS wait implementation where the max_events parameter is not validated against the provided events slice length, which could lead to an out-of-bounds panic.

@mtjhrc mtjhrc force-pushed the dont-alloc-epoll-events branch 2 times, most recently from 524a418 to a3e0e78 Compare April 1, 2026 11:34
mtjhrc added 2 commits April 1, 2026 13:37
Replace the per-call Vec allocation in Epoll::wait with a Vec field
that is allocated lazily, resized and reused across wait calls.

Implement Clone manually so that each clone gets its own fresh empty
buffer.

This also fixes a bug: the old code sized the kevent buffer to
events.len() but passed max_events as the kernel limit. The correct
size is max_events, since that is what the kernel uses. In practice
all call sites pass the same value for both, so no behavioral change.

Signed-off-by: Matej Hrica <mhrica@redhat.com>
Move the epoll_events Vec allocation before the loop in all virtio
worker threads (block, fs, net, snd, vsock muxer). The buffer is
reused across iterations since wait() overwrites entries and all
callers only iterate epoll_events[0..ev_cnt].

Signed-off-by: Matej Hrica <mhrica@redhat.com>
@mtjhrc mtjhrc force-pushed the dont-alloc-epoll-events branch from a3e0e78 to 7132d95 Compare April 1, 2026 11:37
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