Currently we set max_open_files = 64
on all architectures due to concerns about file descriptor exhaustion. This is extremely expensive due to how LevelDB is designed.
When a LevelDB file handle is opened, a bloom filter and block index are decoded, and some CRCs are checked. Bloom filters and block indexes in open table handles can be checked purely in memory. This means that when doing a key lookup, if a given table file may contain a given key, all of the lookup operations can happen completely in RAM until the block itself is fetched. In the common case fetching the block is one disk seek, because the block index stores its physical offset. This is the ideal case, and what we want to happen as often as possible.
If a table file handle is not open in the table cache, then in addition to the regular system calls to open the file, the block index and bloom filter need to be decoded before they can be checked. This is expensive and is something we want to avoid.
The current setting of 64 file handles means that on a synced node, only about 4% of key lookups can be satisifed by table file handles that are actually open and in memory.
The original concerns about file descriptor exhaustion are unwarranted on most systems because:
- On 64-bit POSIX hosts LevelDB will open up to 1000 file descriptors using
mmap()
, and it does not retain an open file descriptor for such files. - On Windows non-socket files do not interfere with the main network
select()
loop, so the same fd exhaustion issues do not apply there.
This change keeps the default max_open_files
value (which is 1000) on all systems except 32-bit POSIX hosts (which do not use mmap()
). Open file handles use about 20 KB of memory (for the block index), so the extra file handles do not cause much memory overhead. At most 1000 will be open, and a fully synced node right now has about 1500 such files.
Profile of loadblk
thread before changes: https://monad.io/maxopenfiles-master.svg
Profile of loadblk
thread after changes: https://monad.io/maxopenfiles-increase.svg