An analysis of APFS enumeration performance on rotational hard drives

An analysis of APFS enumeration performance on rotational hard drives

My APFS-formatted rotational disks have always felt slower than when they were HFS+ formatted. The speed of copying files to them felt about the same, but slogging through folders in the Finder was taking a lot longer. At first I shrugged it off to the filesystem being new; "It just needs some tuning, it will come along." But that performance hasn't come along, and after running some tests and collecting a lot more data, I'm convinced that Apple made a fundamental design choice in APFS that makes its performance worse than HFS+ on rotational disks. Performance starts out at a significant deficit to HFS+ (OS X Extended) and declines linearly as you add files to the volume.

The rest of this article is fairly technical, here are the key takeaways:

  • Enumerating an APFS filesystem on a traditional HDD (rotational disk) will take 3-20X longer than HFS+ on the same hardware.
  • This performance difference is most noticeable on a macOS startup disk that is (or includes) a rotational disk.
  • If Apple doesn't make some concessions in the APFS filesystem to accommodate the slower seek performance of HDD devices, then a rotational device will never be able to provide acceptable performance as a production macOS startup disk.

Test Setup

I wanted to see how an APFS formatted volume performs over time under "normal" usage conditions and how that compares to an HFS+ formatted volume under the exact same conditions. To do this, I had to set up a simulation that would produce identical changes on two volumes to allow for a consistent, objective analysis of the filesystem performance. When I refer to "filesystem performance," I'm specifically referring to how long it takes the filesystem to do transactional tasks. Read and write performance depends almost entirely on the speed of the media, so I wanted to factor that out of my tests. Enumerating the contents of the filesystem is a good exercise of filesystem transactional performance, so I decided to test the enumeration of 1 million files on each an APFS and HFS+ filesystem over a period of simulated modifications to the filesystem.

The destination device in these tests is a 2TB Western Digital MyBook Duo split into two equal partitions. One partition is formatted HFS+, the other APFS. Spotlight was disabled on both volumes. Snapshot support and APFS defragmentation were varied in different tests to determine whether they had any effect on filesystem performance.

The number of files in the file set is constant – 1 million files, 111,000 directories (files nested three directories deep). To make the simulation closer to real-life, the file size distribution roughly follows 1/x2 – it’s weighted more heavily towards smaller files. Each individual file size is determined randomly, but in a pattern that follows that size distribution histogram. Average data set size is ~18GB. Max file size is 20GB. The payload data is randomly generated, non-zero data. At the end of each cycle, a random selection of 5% of the files are replaced with a randomly-selected file size (again, matching the histogram). Average size of the replacement data set is <1GB. Replacement data is randomly generated. Files are replaced atomically.

Carbon Copy Cloner was used to facilitate the file copying, but a separate utility was created for data collection (that tool uses fts*() system calls to perform the filesystem enumeration). There are three backup tasks: Source > HFS+, Source > APFS. A third "stub" task imposes a 10-second "quiescence" delay, runs the tool to collect performance metrics, makes the randomized changes to the source, then starts the cycle over again. This cycle was repeated 20 times, simulating the kind of disk usage that might occur over several weeks or months. The duration of the copying tasks was not recorded – we're only interested in the transactional performance of the destination filesystems, so we're only measuring the enumeration performance of the destination volumes after making changes to those filesystems.

Results

Enumeration on HFS+ was very consistent in all five simulations; always between 20 and 27 seconds. APFS enumeration started at about 80 seconds, but increased in a linear manner to about 300 seconds in the first ten cycles, then leveled off around 300-380 seconds after 20 cycles.

Enumeration of 1M files on an HDD Device

Because the tests were repeated over a short time interval, a modified version of CCC was used that would retain all snapshots on the destination APFS volume, thus simulating the result from daily backups. I then repeated the simulation with snapshots disabled on the APFS destination. The results of this test were unexpected, so I repeated that same test again and got the same results. Enumeration performance was consistently worse when snapshots were not retained on the destination. In the fourth simulation only some of the snapshots were retained and I found more erratic results, albeit directly between that of the test with snapshots disabled and all snapshots retained. Finally, for the fifth simulation defragmentation was enabled on the APFS destination volume via diskutil. I found no significant difference in enumeration performance when defragmentation was enabled.

Discussion

After the very first simulation, APFS starts at a deficit — APFS takes three times as long to enumerate a million files on a rotational disk compared to HFS+ enumerating the exact same collection of files on the exact same hardware. This result on its own is staggering. As you add and remove files from the volume, however, the performance continues to decline. After just 20 cycles, APFS enumeration performance is 15-20 times worse than HFS+ performance.

Audibly you can hear a significant difference between enumeration on each filesystem. Enumeration on APFS is very chatty. With HFS+, there’s almost no noise at all. So, why is APFS enumeration performance so much worse than HFS+ on rotational media? The answer lies in how rotational disks retrieve data from the media, and how APFS and HFS+ arrange the file data and filesystem metadata on the media. Consider the graphic below:

Artists interpretation of physical allocation of files and filesystem metadata on rotational media

HFS+ preallocates space on the disk for filesystem structures (that's the light blue section). As you add files to the volume, the file data (green) goes to the end of the disk, but the filesystem metadata (e.g. the file name and attributes, the folder hierarchy) stays clumped together. When you enumerate the files on that volume, the drive head has very little moving to do to read all of the filesystem structures.

APFS, on the other hand, does not clump filesystem metadata together, rather it's stored alongside the file data. When you enumerate files on an APFS volume, the drive head has to constantly dart back and forth across the platter to fetch each individual file and folder records. This activity generates the "chatter" that you hear when an APFS-formatted HDD is doing filesystem enumeration, and it's this high-latency seek performance of the HDD that causes enumeration to go so slowly. This only gets worse over time, because you're adding file data and filesystem metadata to the end of the disk, thus always spreading filesystem metadata further out on the disk.

Solid State Drives don't have this seek penalty. SSDs can read the first and last block of the device without any seek penalty at all. Remember when Apple introduced APFS and said that it was "optimized for Flash/SSD storage"? This randomized placement of data and filesystem metadata may have been what they were referring to, and another way of saying that would have been, "APFS is not optimized for HDDs."

Can't APFS defragmentation help with this?

Apple quietly added a defragmentation feature to APFS in macOS Mojave. APFS defragmentation is disabled by default, and only lightly documented in the diskutil man page. Apple gives no indication of what this defragmentation feature actually does, in particular whether it defragments filesystem structures. Based on the results of the tests above, however, I would conclude that APFS defragmentation does not cause filesystem metadata to be physically clumped together on the disk.

How does this performance affect me directly?

Typically when you're using a filesystem, you're not attempting to enumerate the whole thing. Enumeration occurs when you're looking for something (not via Spotlight, but browsing through folders), and it occurs with gusto when you open up the Get Info panel on a folder. So when you're trying to see how large a folder is or browsing through several folders, that's going to take a lot longer on an APFS volume atop rotational media than it is on an HFS+ volume on the same hardware.

The other time that the performance difference will be starkly noticeable is when you're booting macOS from a rotational HDD. macOS seeks and stats thousands of files during the startup process, and if that's taking 15 times longer on a rotational disk, then your 30-second startup process is going to turn into 8 minutes. When the system does finally boot, the system and apps will still feel sluggish as all of your applications load, and those applications each stat hundreds of files. The system is still usable, especially as a rescue backup device, but it's not the kind of experience you'd want for a production startup disk nor for a high-stress restore scenario.

The bottom line is this — If Apple doesn't make some concessions in the APFS filesystem to accommodate the slower seek performance of HDD devices, then a rotational device will never be able to provide acceptable performance as a production macOS startup disk. If performance of your rescue backup is of paramount importance, then you should consider replacing your HDD backup disk with an SSD. We offer some suggestions here.

Does this mean I should avoid using APFS on my HDDs?

No, let's not throw out the baby with the bath water. APFS has loads of really nice features, like snapshots and volume space sharing. Managing volumes within an APFS container is a dream compared to the older method of preallocating space to specific partitions. It's important to understand why we might expect to see performance differences between the two filesystems and when that might impact your use of the filesystem, but this one performance aspect on its own isn't enough reason to avoid it.