Where they’re wrong is about the performance analysis:
> In section 3.2 "I/O stalls" is again a non-issue; no matter how your DBMS handles I/O internally, synchronously or asynchronously, the calling application can't make any progress until the I/O completes, and if the data isn't already in memory then the application must wait.
A TLB shoot down request to pull in a page or evict it can cause pauses not just in your own application but also many others because it’s basically a system wide mutex. There is a trade off obviously where the kernel can evict I/O buffers more efficiently. But to me all that says is that the interface for managing I/O buffers in user space is really immature and needs some better performing API so that we have something in between mmap and buffer management. Also an asynchronous application can switch to doing other work. If your synchronous memory access is blocking your thread, other unrelated work is being blocked.
As for workload optimization, I think OP is overstating how much sharing resources mitigates this - when I’m doing a blind search through all data for some reason (maybe some kind of background GC) or a range lookup I can choose to not cache any of that data. Similarly, if I’m doing a point lookup I can do a pre read. However, mmap has no higher level concept about the workload that’s accessing the memory. This a very real problem the kernel tried to tackle back in the 90s / early 00s when disk indexing was starting out - a disk index would cause the cache for all other apps to be evicted resulting in waking up to a sluggish machine paging everything back in.
The more high level context you can retain, the better your decision making about resource allocation is. When that high level context is lost/discarded you lose efficiency.