News for hackers. Stuff that matters.
Re:Mio – Cross-platform header-only C++11 library for memory... by quotemstr on Saturday October 20, 2018 @11:54AM (#18263818)
I wish people used mmap less.

Creating a new memory mapping can be pretty expensive! On both Windows and Linux, it involves taking a process-wide reader-writer lock in exclusive mode (meaning you get to sit and wait behind page faults), doing a bunch of VMA tree manipulation work, doing various kinds of bookkeeping (hello, rmap!) and then, after you return to userspace, entering the kernel again in response to VM faults just to fill in a few pages by doing, inside the kernel, what amounts to a read (2) anyway!

Sure, if you use mmap, you get to look at the page cache pages directly instead of copying from them into some application-provided buffer, but most of the time, it's not worth the cost.

There are exceptions of course, but you should always default to conventional reads.

Re:Mio – Cross-platform header-only C++11 library for memory... by osivertsson on Saturday October 20, 2018 @01:07PM (#18264208)
Another problem with mmap is that there is no good way to handle I/O errors.

The application will get a signal (SIGSEGV/SIGBUS, can't remember), and no information about what the problem could possibly be. Most applications do not catch these signals and will instead just terminate.

Even if you do catch the signal there is a real challenge to know what caused the signal and to keep consistent book-keeping to be able to perform any sane action in response.

At a previous employer we started seeing this problem when scaling things in production which was no fun.

Re:Mio – Cross-platform header-only C++11 library for memory... by __sr__ on Sunday October 21, 2018 @02:57AM (#18267013)
I was burnt by a third party application using mmap over NFS recently. Definitely not fun by any definition of it.

And it gets a SIGSEGV and segfaults.

Re:Mio – Cross-platform header-only C++11 library for memory... by pradn on Saturday October 20, 2018 @01:53PM (#18264481)
A library that helped manage MMAP errors would be extremely helpful.
Re:Mio – Cross-platform header-only C++11 library for memory... by quotemstr on Saturday October 20, 2018 @03:07PM (#18264876)
I wanted to help address this problem with my signal sharing API proposal. Unfortunately, the glibc people have the attitude that nobody should be using signals, and so they refuse to improve the signals API at all. I strongly disagree.

https://www.facebook.com/notes/daniel-colascione/toward-shar...

Re:Mio – Cross-platform header-only C++11 library for memory... by spc476 on Saturday October 20, 2018 @05:46PM (#18265667)
There's a reason for that---signals are horribly abused as a general purpose signaling mechanism. Originally they were for signaling of actual problems in the code (SIGSEGV, SIGILL) but later signals were not (SIGWINCH I'm looking at you!).

I read the page you linked to, and just off the top of my head, trying to manage paging by catching SIGSEGV is how do you determine that it's in response to a real bug (say, dereferencing an undefined pointer)? In my opinion, by the time you get a SIGSEGV, you can't trust the program at all. While it might be nice to have a process handle page faults itself, I think a better API than signal() is required.

Re:Mio – Cross-platform header-only C++11 library for memory... by quotemstr on Saturday October 20, 2018 @07:23PM (#18265996)
To distinguish the SIGSEGVs that represent crashes from ones representing faults you care about, you look at the fault address. It works perfectly well: every high performance Java or C# runtime on Linux (e.g., HotSpot, ART) does it. You can trust the program, because SIGSEGV delivery isn't magic.

As I detailed in the doc and on libc-alpha, you really do need some kind of synchronous exception mechanism to match how real hardware behaves, and it would behoove libc authors to make this mechanism not suck instead of pretending that synchronous faults would just go away.

Re:Mio – Cross-platform header-only C++11 library for memory... by mcguire on Saturday October 20, 2018 @10:26PM (#18266470)
Aaaaah. Memories.

If you caught SIGSEGV on AIX 3.2.5 to manage a mapped NFS file, you deadlocked that filesystem. Great fun!

Thanks for the flashback!

Re:Mio – Cross-platform header-only C++11 library for memory... by gmueckl on Saturday October 20, 2018 @12:15PM (#18263937)
If you are reading large chunks of data at once - and you should - then the same process happens, but it is hidden inside the memory manager.

I, for one, used memory mapping in the past to significantly speed up code that operates on gigantic data sets. I guess that your mileage does vary.

Re:Mio – Cross-platform header-only C++11 library for memory... by jabl on Saturday October 20, 2018 @02:50PM (#18264800)
Case in point, a sort-of general purpose IO library was using mmap as the OS interface, and presenting a read/write style API. We had various bugs related to this (e.g. extending or truncating a mmap'ed file is slightly tricky to do correctly etc.).

I ripped out the mmap codepath, fixing the mmap-related bugs, and for some benchmarks performance improved by a factor of 20.

Now, there are certainly places where mmap is awesome. E.g. if you can push the mmap semantics up to the application level, or you need the sharing semantics etc.

Re:Mio – Cross-platform header-only C++11 library for memory... by mandreyel on Saturday October 20, 2018 @12:15PM (#18263936)
This is a valid point. My use case was very frequent reads of large files at pretty much unpredictable positions, so in theory mmap seemed justified. However, I never got around thoroughly testing this assumption, and may indeed just have been better off using read(2) and its variants.

You seem very experienced, so I hope you don't mind a question. In my use case the files were as large as tens of gigabytes and I was creating read-only mappings of 256KB-1MB chunks in them, keeping the mmap handles around according to a cache policy and RAM usage limit. Do you think in this case using mmap could in theory introduce performance gains?

[edit: typo]

Re:Mio – Cross-platform header-only C++11 library for memory... by gmueckl on Saturday October 20, 2018 @12:20PM (#18263962)
I think that this is the wrong way to use mmap. Just map the whole file at once. The operating system will automatically read the pages you access from disk. And if memory gets tight, these pages will be flushed to disk if they are dirty and then discarded before the system starts paging. These mmapped pages essentially live in the disk cache.
Re:Mio – Cross-platform header-only C++11 library for memory... by mandreyel on Saturday October 20, 2018 @12:53PM (#18264124)
Hmm, I see, I haven't come across this suggestion but I may not have researched this topic well enough. I'll try your suggestion next time.

I appreciate the responses--learned something new today!

Re:Mio – Cross-platform header-only C++11 library for memory... by quotemstr on Saturday October 20, 2018 @12:32PM (#18264020)
> The operating system will automatically read the pages you access from disk. And if memory gets tight, these pages will be flushed to disk if they are dirty and then discarded before the system starts paging.

You can tell that you understand how modern OS memory management works when you realize that the OS "automatically read[ing] the pages...from disk" and "flush[ing them] to disk" on memory pressure is paging whether those pages are anonymous pages or mmaped file pages. :-)

[Edit: flushing dirty file-paged pages is analogous to swapping anonymous memory to the swapfile. Discarding clean file-backed pages is a bit like discarding anonymous pages that have been made unused through munmap, process death, etc.]

But to the GP's point: you don't need (except to conserve address space) to limit file mapping size. I think he really wants something like MADV_FREE. But it's complicated.

Re:Mio – Cross-platform header-only C++11 library for memory... by gmueckl on Saturday October 20, 2018 @12:47PM (#18264095)
Therr is a subtle difference between anonymous and mapped readonly pages: the later can be discarded right away because their contents were read from permanemt storage to begin with. Anonymous pages need to be written to disk first and that is significantly slower.
Re:Mio – Cross-platform header-only C++11 library for memory... by jnordwick on Saturday October 20, 2018 @01:01PM (#18264171)
Yeah +1 for someone who understands mmap.
Re:Mio – Cross-platform header-only C++11 library for memory... by quotemstr on Saturday October 20, 2018 @12:29PM (#18264003)
Random access to large files is a legitimate use case! LMDB [1] uses a similar technique, and it works well for them. But depending on the specific application, explicitly application-managed caching via O_DIRECT IO with something like threaded pread or AIO might be even better, because with this explicit model, you control the cache sizing and eviction policy, and it's certainly possible with application-level knowledge to do better than the generic kernel-level LRU/active/inactive/kinda-sorta-works-heuristic stuff can do without application-specific knowledge.

Another advantage of using application-managed caching is the ability to take advantage of things like huge pages (which can drastically reduce TLB miss rates), whereas with conventional mmap of conventional files, you're limited to regular 4kB (or whatever) small pages and associated management overhead. (There's no reason in principle filesystems can't use huge pages for page cache, but AFAIK, nobody does it yet.)

OTOH, kernel management of page cache allows for better integration of cache eviction with system memory pressure signals and allows for multiple users of a single file to share the memory mirroring the contents of that file.

> Do you think in this case using mmap could in theory introduce performance gains?

It depends. The right approach depends on a lot of factors, including workload and developer complexity budget. It's funny, really: the more experience you get, the less likely you are to say "$SOLUTION is the bestest evar!" and the more often you say "well, it really depends, so I can't give you an answer".

What really strikes me as needless is someone using mmap to read a 10kB ~/.myapplication.lol.ini file or something.

[1] http://www.lmdb.tech/doc/

Re:Mio – Cross-platform header-only C++11 library for memory... by mandreyel on Saturday October 20, 2018 @02:02PM (#18264532)
Oh, I missed this response (still a little overwhelmed). I'm so glad I checked again because there is some precious wisdom in there. Thank you for taking the time to write it down. And it indeed seems like I was misusing mmap...well, next time I'll know better!
Re:Mio – Cross-platform header-only C++11 library for memory... by cbsmith on Saturday October 20, 2018 @02:46PM (#18264780)
Nothing wrong with using mmap for this, though I'd just do a big map of the whole file. That said, you can achieve similar results with readv...
Re:Mio – Cross-platform header-only C++11 library for memory... by gok on Saturday October 20, 2018 @01:57PM (#18264503)
The cost of the second kernel trip (on the first page fault) is often mitigated by speculative read-ahead, or the fact that a given page is often in the UBC already. And file-backed memory doesn't contribute to dirty memory. And mmap() makes it easy to use read-only memory, which catches memory corruption bugs. Plus it's easier to use huge pages, which reduces TLB pressure.

I <3 mmap

Re:Mio – Cross-platform header-only C++11 library for memory... by nemo1618 on Saturday October 20, 2018 @11:24PM (#18266592)
>mmap() makes it easy to use read-only memory, which catches memory corruption bugs

You might appreciate this toy Go package I hacked together: https://github.com/lukechampine/freeze

It uses mmap and mprotect to "freeze" Go objects; if you try to modify a frozen object, the program crashes.

Re:Mio – Cross-platform header-only C++11 library for memory... by gok on Sunday October 21, 2018 @12:16AM (#18266706)
Nice!
Re:Mio – Cross-platform header-only C++11 library for memory... by jzwinck on Saturday October 20, 2018 @08:25PM (#18266202)
Memory mapped I/O actually prevents the use of huge pages if the backing storage is an actual disk. See https://lwn.net/Articles/718102/

Do you know of a way around that, aside from building your own patched kernel?

Re:Mio – Cross-platform header-only C++11 library for memory... by gok on Sunday October 21, 2018 @12:28AM (#18266733)
Yeah you need to move your files to tmpfs, but I still consider that easier than dealing with making it happen with malloc+read