Is it possible to manually TRIM the unused blocks (free space) for an existing APFS volume?

When migrating a MacBook from HDD to SSD, I did a block-level copy using dd. I believe for optimal flash lifetime and performance, it would be the best to issue a TRIM for every unused block in the new filesystem to inform the SSD controller (so it won't confuse my dd copy with a large file that occupies the entire disk).

Is it possible to TRIM the free space manually for an APFS volume on macOS (like FreeBSD's trim or Linux's fstrim)? I've read that on HFS+, macOS's fsck has a TRIM pass, so TRIM can be triggered manually by running fsck -fy in single-user mode, and one should see a "trimming unused blocks" message. But it doesn't support APFS (I tried it and I didn't see any message about TRIM).


Solution 1:

On APFS, macOS automatically performs a TRIM operation on the free disk space on boot via the AFPS Space Manager (spaceman). Therefore, as long as TRIM is enabled on the system (via trimforce for 3rd-party SSDs, see karolus's answer), you don't have to worry about it. There is no command and no need to manually trim the unused blocks.

Verification

If you want to personally verify the operation of boot time TRIM, you can search for spaceman-related messages in your boot log.

Execute the following command as root. It lists all messages from the kernel (--predicate "processID == 0") since the beginning of this month (--start $(date "+%Y-%m-01") and search for messages that contain "spaceman" (grep spaceman).

# log show --predicate "processID == 0" \
  --start $(date "+%Y-%m-01") | grep spaceman

And you can see messages like these

2021-01-13 11:54:28.559149+0800 0x1bc      Default     0x0                  0      0    kernel: (apfs) spaceman_trim_free_blocks:3009: scan took 7.102084 s, trims took 6.415750 s
2021-01-13 11:54:28.565684+0800 0x1bc      Default     0x0                  0      0    kernel: (apfs) spaceman_trim_free_blocks:3017: 28059445 blocks free in 247937 extents
2021-01-13 11:54:28.572872+0800 0x1bc      Default     0x0                  0      0    kernel: (apfs) spaceman_trim_free_blocks:3025: 28059445 blocks trimmed in 247937 extents (25 us/trim, 38645 trims/s)
2021-01-13 11:54:28.580121+0800 0x1bc      Default     0x0                  0      0    kernel: (apfs) spaceman_trim_free_blocks:3028: trim distribution 1:25496 2+:47953 4+:92857 16+:41261 64+:17838 256+:22532

The lines are too long to read, I slightly edited it to make it shorter. You should see logs lines that mentions "TRIM",

scan took 7.102084 s, trims took 6.415750 s
28059445 blocks free in 247937 extents
28059445 blocks trimmed in 247937 extents (25 us/trim, 38645 trims/s)
trim distribution 1:25496 2+:47953 4+:92857 16+:41261 64+:17838 256+:22532

As you can see, macOS just trimmed 28059445 unused blocks today. Assuming APFS uses a 4 KiB block size, it means the SSD has discarded 107 GiB of free space. And yes, it roughly matches the free space on my disk. Works as expected!

Solution 2:

Per cnet, you should be able to check if TRIM is running (article has video) under System Information > SATA. If it isn't available, per the article, run:

sudo trimforce enable

Approving it will require a restart, but you should be able to verify it's now enabled back under System Information.

Additionally, APFS-formatted volumes will automatically run TRIM on boot, so no commands will be listed to manually do this.