Mmap(2)
jmoiron.net
jmoiron.net
At first junior developers don't know about it, then, they read a blog, hear something at a meeting about it and all of the sudden they fall in love with mmap. Then they want to re-write every storage related thing using it claiming it will be lightning fast and efficient. "You just write to memory and kernel writes to file, that so awesome, here I refactored your storage backend to use it over the weekend!"
Some might even venture to write whole database products based on it.
But then one day they "grow up" and realize what a great pain mmap can be, their storage backend is being hammered constantly by input data and dirty pages are not flushed fast enough, and then they are they start blocking other processes for seconds at a time. THey start tweaking madvise setting trying to control behavior, adjusting number of pdflush threads, etc. Or, and also sigbus errors are fun...
The kernel is smarter than your app. Trying to force it to do something it doesn't want to do is a very bad idea.
However, any option worth disabling can be disabled. Nothing needs to be forced off like the writer of the article did. mmap'd writes should be flushed as soon as possible, not dragged out, especially in the SSD age we have today. What the writer did was actually counterintuitive and makes no sense. None.
It's funny how code written by masters tends to look a lot like code written by novices, while intermediate-level code is full of baroque architecture and clever tricks that don't work. The difference between master code and novice code is that a master knows when he can get away with simplicity.
What about fastest product that run 1M TPS but crashes and is down 10 days per month? Is that still fastest?
I've discovered mmap 25 years ago on SunOS, I haven't outgrown it yet -- it has served me well over the years, and I expect it will continue to do so ;-)
I'm not sure what those pains are that you are talking about. mmap allows use to share buffers with the OS in a way that is much more efficient than you can do with plain reads; it costs you some asynchrony and (practically these days) the ability to use a 32-bit processor.
Other than that, it is the same - you still have to reason about locality of reference and stuff.
The Apollo DOMAIN OS was entirely built around single-level store, i.e. memory-mapped files. It scaled well beyond anything Sun was building in those days, even across large networks.
The whole idea of system calls being expensive is obsolete now that we're not using heavyweight software interrupts to implement them.
What the fuck do you think happens when you write to a mmap(2)ed page anyway? The kernel has to know the page is dirty somehow so that it can remember to flush it later. It learns about page dirtying by initially mapping the page read-only, letting the CPU fault when you try to write, marking the page dirty, and letting the write proceed.
You're entering the kernel either way.
In the vast majority of cases, you want plain read and write. In the vast majority of cases, the overhead of jumping into the kernel is not your bottleneck. Simplicity counts for a lot.
The reason LMDB can pack so much functionality into only 7KLOCs is because using mmap is much simpler than using read() and maintaining a user-level buffer cache.
In the vast majority of cases, developers need to profile their code if they actually care about performance - and fail to do so.
I used to read these reports as they came out, very interesting.