APFS copied a 2 GiB file in under 10 ms and used no disk space
Copy-on-write means a file copy on your Mac can be free in both time and space. Here is the same 2 GiB copied both ways, timed, with the disk usage measured before and after.
Copying a 2 GiB file on this Mac took less than ten milliseconds and consumed no disk space. Copying the same file a different way took 1.05 seconds and consumed 2047 MiB. Both produced a complete, independent, fully readable 2 GiB file. The difference is one flag, and the mechanism behind it explains several otherwise baffling things about how storage behaves on macOS.
The test
A 2 GiB file of random data, so that nothing can be compressed away:
dd if=/dev/urandom of=big.bin bs=1m count=2048
2147483648 bytes transferred in 4.264637 secs (503556023 bytes/sec)
Then three clones and one conventional copy, with free space measured around each.
# Clone: ask APFS to share the blocks
cp -c big.bin clone1.bin
# Copy: read every byte and write it again
cp big.bin realcopy.bin
What happened
| Operation | Time | Free space consumed |
|---|---|---|
| Clone, run 1 | 0.00 s | — |
| Clone, run 2 | 0.00 s | — |
| Clone, run 3 | 0.00 s | — |
| All three clones | — | 4 KiB total |
| Conventional copy | 1.05 s | 2047 MiB |
/usr/bin/time -p reports to 10 ms, and all three clones came in under that floor. The correct statement is that each clone took less than ten milliseconds, not that it took zero time.
The space figure is the more striking one. Three clones of a 2 GiB file, six gibibytes of apparent data, cost 4 KiB of actual disk between them.
Why the clone is free
A conventional copy reads 2 GiB from storage and writes 2 GiB back. There is no way to make that cheap.
A clone writes no data at all. APFS creates a new file record whose extents point at the same physical blocks the original uses, and marks those blocks as shared. Two directory entries, two independent files as far as anything above the filesystem is concerned, one set of blocks underneath.
The blocks become copy-on-write. Neither file may modify a shared block in place. When you write to one of them, APFS allocates a fresh block, writes the modified content there, and repoints only that file’s extent at the new location. The other file is untouched because nothing it points at ever changed.
The cost of an edit is therefore proportional to what you edited, not to the file size. Changing one byte in a 2 GiB clone allocates one block.
Two tools that disagree afterwards
With one original, three clones and one real copy on disk, ls reports:
2147483648 big.bin
2147483648 clone1.bin
2147483648 clone2.bin
2147483648 clone3.bin
2147483648 realcopy.bin
Ten gibibytes of files. du -sh on the directory agrees:
10G .
df disagrees, and df is right. Actual consumption was 2 GiB for the original plus 2047 MiB for the real copy, so roughly 4 GiB. The clones added nothing.
The reason is that du walks each file and totals the blocks that file references. A block shared by four files is counted four times, because du has no cheap way to know it has already seen it. df asks the volume how much space is allocated, which counts each block once.
This is worth remembering in general: on APFS, du overstates consumption whenever cloning is involved, and df is the figure that matches what you can actually still write.
Where this shows up without you asking
Cloning is not a niche feature you have to opt into. It is the default path for several ordinary operations.
Duplicating a file in Finder clones it, which is why duplicating a 40 GB video file is instantaneous and does not halve your remaining space. Moving a file between folders on the same volume never copies data. Time Machine local snapshots are built on the same block-sharing machinery, which is why a snapshot of a full disk does not immediately require another full disk.
It also explains a class of confusing storage reports. If Finder tells you a folder contains 60 GB and your free space does not increase by 60 GB when you delete it, shared blocks are the likely reason: some of those blocks are still referenced by something else, so deleting one reference frees nothing.
The honest caveats
The conventional copy completing 2 GiB in 1.05 seconds implies roughly 2 GB per second, which is fast enough to suspect the page cache was involved rather than that number representing sustained SSD write throughput. The file had just been written, so much of it was likely still in memory. That does not affect the comparison, since the clone was three orders of magnitude faster regardless, but the 1.05 second figure should not be quoted as a disk speed benchmark.
The clone timings hit the resolution floor of the timer, so the only defensible claim is “under 10 ms”. Measuring the actual duration would need a higher-resolution timer, and the result would still be dominated by the cost of creating a directory entry rather than by anything related to the file size.
Trying it yourself
mkdir clonetest && cd clonetest
dd if=/dev/urandom of=big.bin bs=1m count=1024
df -k . | tail -1
cp -c big.bin clone.bin
df -k . | tail -1 # free space essentially unchanged
cp big.bin copy.bin
df -k . | tail -1 # free space down by 1 GiB
cd .. && rm -rf clonetest
Watch the free space column across the three df calls. The clone leaves it alone. The copy does not.
What happens when you edit a clone
The claim that an edit costs only what you edited is checkable.
mkdir clonetest && cd clonetest
dd if=/dev/urandom of=orig.bin bs=1m count=512 2>/dev/null
cp -c orig.bin clone.bin
df -k . | tail -1 # baseline
# Overwrite the first megabyte of the clone only
dd if=/dev/urandom of=clone.bin bs=1m count=1 conv=notrunc 2>/dev/null
df -k . | tail -1 # up by ~1 MiB, not 512
cd .. && rm -rf clonetest
Free space drops by roughly the size of what you wrote, not by the size of the file. The blocks you did not touch are still shared. This is what copy-on-write means in practice, and it is why a clone is not merely a cheap copy at creation time but stays cheap for as long as the two files remain mostly identical.
The corollary is that a clone becomes an ordinary copy gradually. Rewrite every block and you have paid the full cost, just spread over time instead of up front.
Where clones come from without you asking
Cloning is the default path for several operations rather than an opt-in feature.
Duplicating in Finder produces a clone, which is why duplicating a 40 GB video file is instantaneous and does not halve your free space. Moving a file between folders on the same volume never copies data at all. Several backup tools, and Time Machine’s local snapshots, are built on the same block-sharing machinery, which is why a snapshot of a nearly full disk does not immediately need another disk.
Two things that are not clones and are worth distinguishing: copying to a different volume is
always a real copy, because blocks cannot be shared across containers; and copying with most
tools other than cp -c is a real copy, because cloning has to be requested explicitly through
the clonefile system call.
# Clone
cp -c source dest
# Real copy, even on APFS
cp source dest
rsync source dest
That asymmetry catches people out when a script that used to be fast becomes slow after being
rewritten to use rsync for its other features.
The reporting problem this creates
Because du counts shared blocks once per referencing file, any directory containing clones is
overstated. On the test above, five files reported 10 GiB while roughly 4 GiB was actually
consumed.
This matters beyond curiosity. Backup tools that estimate transfer size from du will overstate
it. Disk usage dashboards will show a machine as fuller than it is. Scripts that check free space
by summing file sizes will reach the wrong conclusion. The reliable question is the one df
answers: how much can still be written to this volume.
Takeaways
- Three clones of a 2 GiB file completed in under the 10 ms timer resolution and consumed 4 KiB of disk between them.
- A conventional copy of the same file took 1.05 seconds and consumed 2047 MiB.
- ls reports all five files as 2,147,483,648 bytes, so apparent size tells you nothing about what is actually stored.
- du reported 10 GiB for a directory holding roughly 4 GiB of real blocks, because it counts shared blocks once per file.
Questions
- Does the Finder use clones when I duplicate a file?
- Yes. Duplicating a file in Finder on an APFS volume produces a clone, which is why duplicating a very large file appears instant and does not reduce your free space.
- What happens when I edit one of the clones?
- Only the blocks you change get written as new blocks, and only those stop being shared. Editing one byte of a 2 GiB clone costs one block, not 2 GiB.
- Why did du report 10 GiB when only about 4 GiB was used?
- du walks files and adds up the blocks each one references. Shared blocks are referenced by several files, so they get counted several times. df measures the volume itself and is the figure to trust for real consumption.
Sources
What we read. Distinct from what we measured, which is in the article itself.