5 ms·
But there were other async APIs on Linux prior to 2019, why jdk didn't use them?
by riku_iki 3y ago
But there were other async APIs on Linux prior to 2019, why jdk didn't use them?
- wmf 3y agoBefore uring, Linux AIO was kind of fake; most operations were blocking. It makes sense that Java would use a thread pool instead of attempting to use Linux AIO.
- formerly_proven 3y agoio uring is similarly “fake async” because it’s also just a thread pool (just owned-operated by the kernel, not a runtime or library). I don’t think anyone has ever bothered to make FS code async, it’s already quite horrible as it is. Not in a mainstream kernel anyway. So you need to be on the FS-less happy path - properly aligned I/O to allocated blocks on some specific FSes - to get async disk IO, this automatically excludes all extending writes and metadata ops. Same for Windows disk IO with IOCPs.
- emily-c 3y ago>I don’t think anyone has ever bothered to make FS code async, it’s already quite horrible as it is. Not in a mainstream kernel anyway. [...] Same for Windows disk IO with IOCPs. IOCP merely allows IO completion to happen on worker threads in a threadpool rather than the particular thread that initiated the IO request. Many concepts in the NT kernel come from a long line of production kernels in mainstream DEC operating systems going back to RSX-11M and VMS. That entire lineage of operating systems (culminating in NT) all have true asynchronous IO using IO Request Packets (IRPs) within the kernel to initiate/queue IO requests and immediately return. There are individual cases within NTFS where blocking will occur but those are special cases rather than the rule as the kernel IO system in general is entirely async.
- jakjak123 3y agoI am not sure if there were any practical async apis for files. There was only for networking I believe?
- riku_iki 3y agoI am not an expert, but my reading is that epoll operates on file descriptors.
- jen20 3y agoThis is highly dependent on the filesystem - as far as I know, basically only XFS works, and only for a small subset of operations, and everything else just blocks. Tokio's filesystem handling in Rust is the same way by default - a pool of IO threads. Edit: I just remembered that Avi Kivity (of KVM and ScyllaDB fame) wrote a tool to detect this: https://github.com/avikivity/fsqual https://github.com/avikivity/fsqual
- gpderetta 3y agoReadiness notification, like epoll, is not really suitable for file backed IO. A file on disk is not a FIFO that you can wait for data to be available; what would even mean for notification to be ready to read for a file fd? Consider that reads can be at any offset. You need completion notifications instead (like IOCP or io_uring or POSIX aio). You could in principle start an async splice from an FD into a pipe and then poll for the pipe to be ready to read, but IIRC there is no async splice.
- deleted 3y ago[deleted]
- saati 3y agoThey are always "ready" and they block when you use them.
- formerly_proven 3y agoSure, in the sense that files are always ready for I/O.
- jlokier 3y agoDespite various attempts at Linux async file APIs over the years, it turned out using a well-implemented thread pool for file I/O was the fastest way to do async file I/O on Linux, in most cases. In cases where it wasn't fastest, it was still close. A thread pool was also more reliable than the kernel APIs at ensuring overlapped I/O for throughout. libaio (kernel API) calls sometimes turned into blocking calls depending on filesystem internals, in a way that thread pools don't. POSIX AIO, on Linux, just uses a userspace thread pool. It's implemented in libc and is not particularly fast. You can do better with your own thread pool. Perhaps Linux threads got faster, faster than the APIs got better. Even with io_uring, in my tests on fast NVMe storage RAIDs where it should make the most difference, I found io_uring wasn't noticably faster than a well-optimised (for Linux) thread pool. io_uring can potentally adapt better to shared workload and different cache situations, because it has access to kernel information that userspace thread pools are not granted. But I was surprised to find no significant random-access I/O performance increase between my thread pool and io_uring, when I was trying to optimise both methods to get the best throughput out of a system.