mmap( ) vs read( )

24,438

Solution 1

It really depends on what you're trying to do. If all you need to do is hop to a known offset and read out a small tag, read() may be faster (mmap() has to do some rather complex internal accounting). If you are planning on copying out all 200mb of the MP3, however, or scanning it for some tag that may appear at an unknown offset, then mmap() is likely a faster approach.

For example, if you need to shift the entire file down a few hundred bytes in order to insert an ID3 tag, one simple approach would be to expand the file with ftruncate(), mmap the file, then memmove() the contents down a bit. This, however, will destroy the file if your program crashes while it's running. You could also copy the contents of the file into a new file - this is another place where mmap() really shines; you can simply mmap() the old file, then copy all of its data into the new file with a single write().

In short, mmap() is great if you're doing a large amount of IO in terms of total bytes transferred; this is because it reduces the number of copies needed, and can significantly reduce the number of kernel entries needed for reading cached data. However mmap() requires a minimum of two trips into the kernel (three if you clean up the mapping when you're done!) and does some complex internal kernel accounting, and so the fixed overhead can be high.

read() on the other hand involves an extra memory-to-memory copy, and can thus be inefficient for large I/O operations, but is simple, and so the fixed overhead is relatively low. In short, use mmap() for large bulk I/O, and read() or pread() for one-off, small I/Os.

Solution 2

Don't bother with mmap unless your code is CPU bound, specifically due to lots small reads and writes. mmap may sound nice, but it isn't the awesome why isn't everyone using this alternative it looks like.

Given that you're recursing through potentially large directory structures, your bottleneck will be directory IO and concurrency. mmap is not going to help.

Update0

Reading the linked to question finds this answer that supports my experience:

Solution 3

If you're not normally going to be streaming the file in and then processing it, but rather hopping around (like read the tags at the front and then jump to the end, etc.) then I would use mmap simply because your code will be cleaner and easier to maintain treating the file as a large buffer without having to actually manage the the buffering and paging yourself.

As has been mentioned, if you're processing a lot of data disk I/O is likely going to dominate your processing anyway. mmap may be faster than read, but for reasonable implementations, it's likely not THAT much faster, especially on todays hardware which has continually got faster and faster while disk drives have been stuck at 7200 and 10,000 RPM for years and years.

So, go with mmap and make your code easy and neat.

Share:
24,438

Related videos on Youtube

J. Andrew Laughlin
Author by

J. Andrew Laughlin

Updated on July 09, 2022

Comments

  • J. Andrew Laughlin
    J. Andrew Laughlin almost 2 years

    I'm writing a bulk ID3 tag editor in C. ID3 tags are usually at the beginning of an mp3 encoded file, although older (version 1) tags are at the end. The app is designed to accept a directory and frame ID list from the command line, then recurse the directory structure updating all the ID3 tags it finds. The user may additionally choose to remove all older (version 1) tags. Another option is to simply display the current tags, without performing an update. The directory might contain 2 files or 2 million. If the user means to update the files, I was planning to load the entire file into memory, perform the updates, then save it (the file may be renamed as well). However, if the user only means to print the current ID3 tags, then loading the entire file seems excessive. After all the file could be 200mb.

    I've read through this thread, which was insightful - mmap() vs. reading blocks

    So my question is, what the most efficient way to go about this -- read(), mmap() or some combination? Design ideas welcome.

    Edit: It's my understanding that mmap essentially delegates loading a file into memory, to the virtual memory subsystem. It seems to me, the VMM would be highly optimized on most systems as it's critical for system performance.

    • rvalue
      rvalue over 12 years
      FWIW, file reading is also pretty optimised as it's also critical to performance. mmap() tends to be slightly faster for random access, read() tends to be faster (or at least, fast enough) for block/streaming access. Read-write mmap() will make it faster and easier to update the tags in-place, if you want to do that - as you only have to map the tag area and writes are effectively direct to the disk buffer.
  • J. Andrew Laughlin
    J. Andrew Laughlin about 13 years
    I'm aware of truncate, however I'm more interested in the performance contrast (if one exists) between read() and mmap() for my particular scenario.
  • musiphil
    musiphil about 11 years
    Hmm, I've read the contrary: use read() for sequential bulk accesses, and mmap() for random-access small accesses.
  • Eamon Nerbonne
    Eamon Nerbonne over 8 years
    @musiphil: you probably should have read that as "use mmap for many small random accesses" - for just a few accesses, it may not be worth it.

Related