Live data from Hacker News

Use mmap with care

sublimetext.com

111–120 of 218 posts

Re: Use mmap with care

#111

Earlier quoted context omitted.

Couldn’t you mmap a shared, read-only page so that your OS doesn’t copy it?

It would be better to mmap the file into N single-threaded processes instead of mmapping the file into 1 N-threaded process. This is exactly why signals are process-global instead of thread-local. The intent is that they were used for inter-process communication. The whole notion of processes and signals predates the notion of a thread, and threads are essentially a performance optimization for 30 or 40 year old hard…

That's because mmap() predates multithreading (at least as a usable production approach rather than a lab experiment). It's best for IPC, not sharing between threads.

I forget sometimes that the young'ns never grew up in a world without threads, and often never learned how unix really works.

Re: Use mmap with care

#112
The problem here was wanting to parse a large file at all. You need to be able to do a) online parsing (so you don't need to read the whole file into memory first), b) stream parse (so you don't need to build a parsed representation of the whole thing before you can do anything).

Re: Use mmap with care

#113

Earlier quoted context omitted.

"strictly worse" despite no-copy memory access? Again, this needs proof.

Strictly worse because it requires more work to maintain and write new code, there's no guarantee we haven't missed any access points in our codebase so it is less robust, still locks files while in use on Windows and requires maintaining patches to Breakpad. Performance is not an issue here, the program working correctly is, and doing so in the long run is strictly worse than mmap.

Do you have a list of these strictly-better things to do and a plan on when to implement them? Do you let them pile up? Mostly asking about your decision-making process.

Re: Use mmap with care

#114
post #84

Honestly, this reads like a thorough indictment of signals in user space. * Signal handlers are process global * Signal handlers need to be re-entrant safe Re-entrancy is painful but can be done, but process-global signal handlers means that pulling in a totally unrelated library can break your code. Moreover, it makes the combined use of certain libraries straight-up impossible. Similarly, it means that the use of l…

Signals are fundamental to the unix design. That'd be like "I want a car, but without any wheels, because wheels are often implicated in crashes".

Depending on OS internals within threading is a problem. Libraries that implement their own signal handling are a problem. Trying to get thread-local signal handling behavior when signals are process-global is a problem.

Threads are not a wholesale substitute for processes. Signals work just fine, as long as you plan for ways they can affect your code's behavior.

Re: Use mmap with care

#115
post #100

Earlier quoted context omitted.

This is essentially how databases like PostgreSQL work, but in essence it only avoids the sys-call overhead. The OS is already caching the file, regardless of mmap, so using pread would have likely been enough for us. It totally would have been simpler overall, but each incremental step we made was significantly less work than the refactoring required for pread.

It totally would have been simpler overall, but each incremental step we made was significantly less work than the refactoring required for pread. Question. In 10 years will you be saying this about the next incremental problem that you run into? If you think this likely, then the next incremental problem is an excuse to do it right.

If it's less work to solve that problem than refactor all the relating code, and the impact on maintainability is minimal, likely yes. But considering the amount of users we have and the current lack of any crashes relating to mmap there are unlikely to be any future unforseen issues.

Re: Use mmap with care

#116

The mistake here is using longjmp / siglongjmp. This is a possible way to handle SIGBUS, but in practice it will be intractable in larger programs written in C or C++. The compiler is generally free to move loads and stores around, and you might be completely blindsided by how the compiler has reordered your memory operations once you add side effects to one of the operations. Theoretically, if accessing a memory loc…

This sounds interesting. Do you know of an example that does this? So if I have multiple threads reading the same mmap'd file, I use si_addr in the signal handler to know which page to call MAP_FIXED on?

I don’t know an open-source example off the top of my head. But that’s the gist of it… you keep an array somewhere with all the address ranges mapped. If you get SIGBUS, find the corresponding map, replace it with zeroes, and mark it as having an error. If there is no corresponding map, uninstall the signal handler and return—the thread will SIGBUS immediately after return and the default action will kill the process.

Re: Use mmap with care

#117
post #66

Author here, if anyone has any questions in relation to me or Sublime HQ please feel free to ask.

I was using Sublime Merge on the weekend and after doing a few changes with my remotes using the normal command line, it exited (well crashed I assume). When things like this happen do you automatically get an error report? Because you mentioned that you use the error reporting library from Google in that article.

We do get crash reports. If you have some more details in relation to this it would be great to hear from you on our forums or on the issue tracker: https://github.com/SublimeTextIssues/Core

Re: Use mmap with care

#118

Earlier quoted context omitted.

Strictly worse because it requires more work to maintain and write new code, there's no guarantee we haven't missed any access points in our codebase so it is less robust, still locks files while in use on Windows and requires maintaining patches to Breakpad. Performance is not an issue here, the program working correctly is, and doing so in the long run is strictly worse than mmap.

Do you have a list of these strictly-better things to do and a plan on when to implement them? Do you let them pile up? Mostly asking about your decision-making process.

I'm not sure what you mean. The blog post discusses solutions to all the problems I listed. They wouldn't have been problems using pread, which has a straight forward implementation.

Re: Use mmap with care

#119

Earlier quoted context omitted.

Did Multics have anything like NFS? Everything is easier if your kernel has control of the underlying device.

Well the problematic example given in the article was NTFS where the whole filesystem can disappear, but the problem applied to local files too, eg if their size is changed by another process.

Where did you see mention of NTFS? I was referring to "As it turns out, the ticket comes from someone using a networked drive."

Re: Use mmap with care

#120

The mistake here is using longjmp / siglongjmp. This is a possible way to handle SIGBUS, but in practice it will be intractable in larger programs written in C or C++. The compiler is generally free to move loads and stores around, and you might be completely blindsided by how the compiler has reordered your memory operations once you add side effects to one of the operations. Theoretically, if accessing a memory loc…

I solved the problem this way recently as well. This solution would also work with multiple threads (you can probably set the flag in thread local storage, though I haven't done that yet - currently using a global map with thread id as key). Though still not with multiple different signal handlers.

That said, if I could do it over I wouldn't use mmap again. Especially since io_uring is around the corner (on Linux) that allows zero-copy reads/writes with no syscall overhead.

Post reply on HN