Saying that an application uses io_uring for input/output provides almost zero information. It provides about the same information as saying that an application is run on Linux.
io_uring is an alternative method of invocation for a very large number of traditional Linux syscalls, and the I/O performance that you obtain depends on which syscalls you use and how you schedule them.
You can use io_uring with classic sequential files, in order to perform the syscalls asynchronously, so you can do other processing in parallel with them, without using multiple threads.
You can use io_uring with mmap, in order to obtain much better performance than they got with mmap.
The file readahead that the kernel does when the user generates page faults is not good enough for reaching maximum performance and it has a great overhead.
For maximum performance with memory-mapped files, the user must take responsibility for the readahead, instead of expecting the kernel to do it.
This is done with madvise, but the best results are obtained by avoiding the POSIX-defined advices, which have wrong semantics, and by using 4 Linux-specific advices:
either MADV_PAGEOUT or MADV_COLD are used to inform the kernel about the pages of the file that can be freed because they will not be reused soon, so that the kernel will have available memory where to do file readahead;
either MADV_POPULATE_READ or MADV_POPULATE_WRITE are used to tell the kernel to read ahead immediately some part of the file instead of waiting for page faults, so if these are used at the right times there will never be any page faults, wasting time.
The madvise syscall must be executed through io_uring, so that it will be executed asynchronously.
When not even controlling the file readahead with madvise provides enough performance, one can replace the memory-mapped files with files opened with O_DIRECT, where all the read/write syscalls are done through io_uring.
By using fixed read/write buffers, O_DIRECT removes the overhead of mmap where each time when pages are read from the file the virtual address translation tables must also be rewritten, and the even greater overhead that happens when pages are freed and all the other processor cores must be informed about this (TLB shootdown).
However, to obtain the performance achievable with O_DIRECT, the programmer can no longer rely on the kernel for I/O scheduling, but this must be handled in the application program, which can bring significant complexity.
This means that all the file reads must be launched enough in advance, so that they will be completed by the time the application needs the data, but one cannot launch too many file reads in advance, because that would consume too much memory.
Whenever O_DIRECT is added without rewriting completely how file I/O is handled in the application, that will lead to reduced performance, not to better performance.