NAME
Hypersonic::Event::IOUring - io_uring event backend for Linux 5.1+
SYNOPSIS
use Hypersonic::Event;
my $backend = Hypersonic::Event->backend('io_uring');
# $backend is 'Hypersonic::Event::IOUring'
DESCRIPTION
Hypersonic::Event::IOUring is the io_uring-based event backend for Hypersonic on Linux 5.1+. It uses io_uring as a readiness notification mechanism via io_uring_prep_poll_add (one-shot, level-triggered POLLIN) and lets the main event loop's userspace accept(2) and recv(2) calls do the actual I/O - the same model as the epoll and kqueue backends, but with submissions batched through the io_uring submission queue.
Why readiness-only, not completion-based?
Hypersonic versions before 0.19 attempted to use io_uring's completion-based I/O model (io_uring_prep_accept + io_uring_prep_recv) where the kernel performs the I/O and returns the result via cqe->res. That design had two unfixable bugs that produced empty HTTP responses and 5000s+ test hangs on CPAN smoker hosts:
The
UD_ACCEPTcompletion'scqe->res(the new client fd) was discarded bygen_get_fdand control fell through to the shared accept loop which calledaccept(listen_fd)- gettingEAGAINbecause the kernel had already handed the connection to io_uring. The connection was leaked.UD_READusedio_uring_prep_recvinto a single globalrecv_buf, so multiple concurrent clients would corrupt each other's request data.
The readiness-only design is simpler, correct, and still benefits from io_uring's batched submission queue (one syscall to arm many polls). Native completion-based I/O could be added in a future release with per-fd buffers and a redesigned accept loop, but is out of scope for the 0.19 fix.
METHODS
name
my $name = Hypersonic::Event::IOUring->name; # 'io_uring'
Returns the backend name.
available
if (Hypersonic::Event::IOUring->available) { ... }
Returns true if this backend is available. Requires:
Linux kernel 5.1 or later
liburing library installed (liburing-dev package)
includes
Returns the C #include directives needed for io_uring.
defines
Returns the C #define directives for io_uring configuration, including user data encoding macros.
event_struct
my $struct = Hypersonic::Event::IOUring->event_struct; # 'io_uring_cqe'
Returns the C struct name used for completion queue entries.
extra_ldflags
my $flags = Hypersonic::Event::IOUring->extra_ldflags; # '-luring'
Returns linker flags needed for liburing.
gen_create($builder, $listen_fd_var)
Generates C code to initialize the io_uring and submit the first accept.
gen_add($builder, $loop_var, $fd_var)
Generates C code to submit a recv operation for a file descriptor.
gen_del($builder, $loop_var, $fd_var)
Generates C code to close a file descriptor (pending operations will complete with an error).
gen_wait($builder, $loop_var, $events_var, $count_var, $timeout_var)
Generates C code to wait for completions with a timeout.
gen_get_fd($builder, $events_var, $index_var, $fd_var)
Generates C code to extract the operation type and file descriptor from a completion queue entry.
gen_cleanup($builder)
Generates C code to clean up io_uring resources on shutdown.
USER DATA ENCODING
As of 0.19, user_data is just the file descriptor cast to void*. The old high-bit-operation-type encoding (UD_ACCEPT / UD_READ / UD_WRITE / UD_FD_MASK) was removed when the backend was rewritten in readiness-only mode. Cancel submissions get NULL user_data so the completion handler can filter them out cheaply.
PERFORMANCE
io_uring can achieve 1.5-2x the throughput of epoll for high-concurrency workloads due to:
Batched submissions (fewer syscalls)
Zero-copy I/O paths
Optional kernel-side polling (IORING_SETUP_SQPOLL)
REQUIREMENTS
Linux kernel 5.1 or later
liburing library:
apt install liburing-dev(Debian/Ubuntu) ordnf install liburing-devel(Fedora/RHEL)
AVAILABILITY
Linux 5.1+ with liburing installed.
SEE ALSO
Hypersonic::Event, Hypersonic::Event::Role, Hypersonic::Event::Epoll
AUTHOR
LNATION <email@lnation.org>
LICENSE
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.