> In brief, every time an SSD updates a single byte anywhere on disk, it needs to erase and re-write that entire page.
Is that actually true for SSDs? For raw flash it’s not, provided you are overwriting “empty” all-ones values or otherwise only changing 1s to 0s. Writing is orders of magnitude slower than reading, but still a couple orders of magnitude faster than erasing (resetting back to “empty”), and only erases count against your wear budget. It sounds like an own goal for an SSD controller to not take advantage of that, although if the actual guts of it are log-structured then I could imagine it not being able to.
>> In brief, every time an SSD updates a single byte anywhere on disk, it needs to erase and re-write that entire page.
> Is that actually true for SSDs? For raw flash it’s not, provided you are overwriting “empty” all-ones values or otherwise only changing 1s to 0s.
Maybe it depends. I wrote the driver for more than one popular flash chips (don't remember which ones now, but that employer had a policy of never using components that were not mainstream and available from multiple suppliers) and all the chips I dealt with did read and write exclusively via fixed-size pages.
Since SSDs are collection of chips, I'd expect each chip on the SSD to only support fixed-size paged IO.
In this scenario I was basically re-writing the entire hard-drive completely in a completely random order, which is the worst case scenario for an SSD.
Normally the controller will use a whole bunch of tricks (e.g. overprovisioning, buffering and reordering of writes) to avoid this type of worst case pattern, but that only goes so far.
1. Writable Unit: The smallest unit you can write to in an SSD is a page.
2. Erasable Unit: The smallest unit you can erase in an SSD is a block, which consists of multiple pages.
So if a write operation impacts only 1 byte within a page, the SSD cannot erase just that byte. However, it does not need to erase the entire block either.
The SSD can perform a "read-modify-write" type of operation:
- Read the full page containing the byte that needs to change into the SSD's cache buffer.
- Modify just the byte that needs updating in the page cache.
- Erase a new empty block.
- Write the modified page from cache to the new block.
- Update the FTL mapping tables to point to the updated page in the new block.
So, a page does need to be rewritten even if just 1 byte changes. Whole-block erasure is avoided until many pages within it need to be modified.
Not precisely. The logical view of a page living at some address of flash is not the reality. Pages get moved around the physical device as writes happen. The drive itself maintains a map of what addresses are used for what purpose, their health and so on. It’s a sparse storage scheme.
There’s even maintenance ops and garbage collection that happens occasionally or on command (like a TRIM).
In reality a “write” to a non-full drive is:
1. Figure out which page the data goes to.
2. Figure out if there’s data there or not. Read / modify / write if needed.
3. Figure out where to write the data.
4. Write the data. It might not go back where it started. In fact it probably won’t because of wear leveling.
You’re right that the controller does a far more complex set of steps for performance. That’s why an empty / new drive performs better for a while (page cache aside) then literally slows down compared to a “full” drive that’s old, with no spare pages.
Source: I was chief engineer for a cache-coherent memory mapped flash accelerator. We let a user map the drive very very efficiently in user space Linux, but eventually caved to the “easier” programming model of just being another hard drive after a while.
Is that actually true for SSDs? For raw flash it’s not, provided you are overwriting “empty” all-ones values or otherwise only changing 1s to 0s. Writing is orders of magnitude slower than reading, but still a couple orders of magnitude faster than erasing (resetting back to “empty”), and only erases count against your wear budget. It sounds like an own goal for an SSD controller to not take advantage of that, although if the actual guts of it are log-structured then I could imagine it not being able to.