How Intel’s SSD Toolbox Optimizer (TRIM) feature works

There is a never-ending supply of people who don’t understand what TRIM is (or as it’s called per ATA specification, DATA SET MANAGEMENT) and how it’s used at the OS level.

How it works

The Optimizer feature creates a large number of what are called sparse files, which NTFS natively supports via the FSCTL_SET_SPARSE flag when calling DeviceIoControl(). For further information about NTFS and sparse files, see Microsoft’s documentation.

Before continuing on, please make sure you understand the concept of a sparse file. Sparse files are not files that are actively filled with data (i.e. not necessarily filled with zeros or some other content), but rather a files on the filesystem which have a predeclared size/length even though data has not been written to that allocated space. In fact, if the files were zeroed or had bytes written to them, not only would the Optimizer take significantly longer to run but would also add excessive wear/tear on NAND pages for no good reason (given what the Optimizer does during its subsequent steps — keep reading).

The files are stored at the root of the filesystem and are named --=={Intel_Trim_File_X}==--.bin, where X is an incrementing integer starting at 0. The files are not marked hidden and are untouchable (non-readable/non-writeable, due to how Windows’ default file locking model works) by processes other than the Optimizer.

The number of sparse files created depends upon how much free space is available on the filesystem; the Optimizer tends to leave exactly 1GByte (1,073,741,824 bytes) untouched while being run. Proof when run on an Intel 510 120GB SSD on Windows XP:

C:\>dir --*
 Volume in drive C has no label.
 Volume Serial Number is 3442-346D

 Directory of C:\

02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_0}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_1}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_10}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_11}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_12}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_13}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_14}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_15}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_16}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_17}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_18}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_19}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_2}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_20}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_21}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_22}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_23}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_24}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_25}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_26}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_27}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_28}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_29}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_3}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_30}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_31}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_32}==--.bin
02/06/2013  16:01       291,819,520 --=={Intel_Trim_File_33}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_4}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_5}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_6}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_7}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_8}==--.bin
02/06/2013  16:01     3,221,225,472 --=={Intel_Trim_File_9}==--.bin
              34 File(s) 106,592,260,096 bytes
               0 Dir(s)   1,073,741,824 bytes free

It’s important to understand that with filesystems, not all data is contiguous (linear); NTFS cluster size or Allocation Unit Size (also often erroneously called “block size”) defines the size of a piece of data at the filesystem level. For example, if your NTFS cluster size is 16KBytes (16,384 bytes), a file that contains 300 bytes would take up 1 cluster (16,384 bytes) on the filesystem, while a file that contains 48,291 bytes would take up 3 clusters (49,152 bytes) on that same filesystem.

But as I said, the important part is to understand that these “clusters” do not have to be contiguous or stored in linear order; they can quite literally be scattered all over the disk (and this is what defragmentation utilities solve). Non-contiguous data only impacts performance with classic mechanical HDDs (MHDDs) due to seek time (which SSDs virtually lack).

How does TRIM fit into this?

So why does the non-contiguous nature of a “cluster” matter when it comes to the Optimizer? Because at the ATA level, TRIM only operates on LBA ranges — it has no knowledge about filesystems. For further details about TRIM, please see specification T13/2015-D revision 3 (working draft) or newer.

In turn, what the Optimizer does after allocating all these sparse files is to calculate the linear LBA ranges which those sparse files actually make up, then proceed to issue the raw DATA SET MANAGEMENT command to the controller for said LBA ranges, which in turn make it to the SSD. The SSD’s flash transition layer (a.k.a. FTL) then knows that LBA regions X to Y do not contain data that the filesystem/OS cares about any longer, and can be removed from (or marked unused within) the FTL map, and subsequently are considered by the SSD as “available for use”.

The sparse files are in effect used to allocate space (at the filesystem level) that can then be safely TRIM’d by the Optimizer itself.

Once all the TRIM operations have completed, the sparse files are deleted.

More about TRIM, its internal behaviour, and performance

Some folks have asked me in the past if the TRIM causes the underlying data at those LBAs to be zeroed, or if the data is simply left alone in a NAND page somewhere, waiting to be overwritten via the standard erase-program methodology of NAND flash.

The answer is: the behaviour depends on the implementation chosen by the SSD vendor. Table 35 of T13/2015-D revision 3 (working draft) specification defines what the methods/models are. Vendors are supposed to disclose the method via the ATA IDENTIFY command (0xec). Rather than explain it verbosely, I’ll just include a picture of the chart itself:

From this we can see that the available methods of operation are:

  1. No TRIM support
  2. TRIM’d LBAs, when subsequently read, may return random/indeterminate data
  3. TRIM’d LBAs, when subsequently read, return a consistent (static) value (e.g. 0xff)
  4. TRIM’d LBAs, when subsequently read, return zero (i.e. 0x00)

The behaviour, as stated before, can be determined per the respective bits in the results of an ATA IDENTIFY command. Whether the SSD vendor chooses to implement that part of the spec is up to them (older SSDs may not, and even newer SSDs may not), and whether or not the utilities and OS you use that issue IDENTIFY to the device support showing you those bits is also up to the programmer and vendor, respectively.

Some operating systems, such as FreeBSD 9.2 and newer, can tell you what TRIM methodology is used by your drive. On FreeBSD, camcontrol identify {disk} (ex. camcontrol identify ada0) will give you this information. Here’s an example:

# camcontrol identify ada0
pass0: <INTEL SSDSA2CW080G3 4PC10362> ATA-8 SATA 2.x device
pass0: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)

protocol              ATA/ATAPI-8 SATA 2.x
device model          INTEL SSDSA2CW080G3
...
Data Set Management (DSM/TRIM) yes
DSM - max 512byte blocks       yes              8
DSM - deterministic read       yes              zeroed
...

The line talking about “deterministic read” is the relevant line. The methodology on the above Intel 320 SSD indicates that “all read ATA commands to the LBA will return the same data” (zeros in this case).

Anyway — regardless of behaviour type, the important part is that the FTL map no longer considers those LBAs (or ranges of LBAs) as “used” by the filesystem.

TRIM is important for this sole reason: the more LBA entries (or LBA ranges) the FTL map contains, generally speaking, the worse the SSD performs.

Without TRIM, the SSD’s FTL map, over time, will lack any indication of available LBA ranges. This in turn forces garbage collection (a.k.a. GC) to be used instead, which is significantly less efficient than the OS (or application) telling the drive “I’m done with these LBAs”. GC has the major downside of halting all I/O to the drive while its internal calculations/analysis are performed (else risk marking an LBA or LBA region as unused at the same time as the filesystem/OS requesting use of that LBA for a legitimate file). The GC implementation and its behaviour varies between drive models and drive vendors, including some vendors going as far as performing actual filesystem-level analysis on the drive itself (something I feel is extremely risky).

Regardless of how efficient GC is today, the fact of the matter remains that performance is significantly worse relying entirely on GC. This is exactly why Intel’s Optimizer feature is so important for OSes which lack native TRIM support.

Furthermore, this is why you should not issue a “full format” (i.e. writing zeros or random data across the entire drive or a partition), sometimes (erroneously) called a “low-level format”, with an SSD. Unlike a classic mechanical HDD, if this is done on an SSD, the FTL map would almost certainly become full immediately afterwards (depending on if the formatting utility chooses to issue TRIM commands to the underlying device after writing zeros or random data to each LBA — in which case, there was no point in writing data there in the first place!).

For the SSD equivalent of a “full format”, the ATA SECURITY ERASE UNIT command (0xf4) should be used. This command resets the FTL map, as well as some other internal bits within the SSD. Intel’s SSD Toolbox “Secure Erase” feature does exactly this. The same can be accomplished within other OSes too.

So what about OSes that support TRIM natively? How does that work? Do I need the Optimizer?

There are many present-day OSes that support TRIM natively. Every Windows OS after Windows Vista has supported TRIM operation natively, while older OSes (like Windows XP) do not have support for it.

An OS having support for TRIM means that the OS will issue TRIM commands to the underlying device on certain I/O operations — the most common and widely used operation is file deletion. It is unknown (to me) whether or not Windows issues TRIM operations when doing other things, such as pruning (shrinking) the page file.

On FreeBSD, for example, TRIM is implemented via what’s called BIO_DELETE, which is used by the kernel for multiple things (not just file deletions). Because FreeBSD is open-source and the developers/engineers can be communicated with directly, knowing what uses BIO_DELETE is possible. With Windows, assumptions have to be made (and I would rather not make those), but it’s well-established that file deletions result in use of TRIM.

A Windows OS that supports TRIM natively does not require the Optimizer to be run. I cannot stress this point enough. In fact, depending on the behaviour of the TRIM implementation (see above), this could actually cause excessive wear/tear on the NAND flash if done repeatedly. Which leads me to…

A short story

In January I dealt with a report from a user stating his Intel 520-series SSD had “crapped out on him”, insisting it was caused by “a firmware bug” reported by some random Internet user (note the username) affecting only 520-series drives that were issued ATA STANDBY or ATA SLEEP commands by the OS, or when the drive was reattached on the SATA bus.

As I began to question his prognosis, he admitted that he was running Windows 7 or 8, did not let his drive go into standby/sleep, and did not excessively remove the drive from the bus. Further pressure revealed that he had scheduled the Intel SSD Optimizer function to run every day at 0300 — and found that his drive “had issues” around that time, repeatedly. Thus, he concluded on his own behalf that he was, somehow, “being bit by this [unsubstantiated] firmware bug”.

I was prompt to lecture him about this; he actually may have killed his own SSD due to his own misunderstanding/negligence of what TRIM is and how it works. I would have be able to determine this if he had provided SMART attributes for the SSD in question, but has since failed to provide them.

This misunderstanding and lack of education is heavily perpetuated by the “PC enthusiast” community, combined by badly-written documentation by vendors, neither of which are that individual’s fault of course. This just goes to show how someone’s lack of understanding of something can actually cause them grief.

An opinionated footnote

Over the past 15 years or so, there has been a growing trend where “PC enthusiasts” have been deemed reliable sources of information when it comes to technology. For every 5000 forum warriors there’s one person (probably an engineer) who actually understands the technology being discussed. While I fully admit SSDs are a fairly new technology that’s rapidly evolving, these “enthusiasts” remain a dominant source of reference material. I say that with as much modesty as possible.

It’s very important to remember that there is a world of difference between an engineer and an enthusiast: one works with the technology (almost certainly professionally) at a very low level, tends to be older (mid-30s and above), and often does not have the time to dedicate to providing information to the masses — while the other is rarely more than an I’ve-got-money-burning-a-hole-in-my-pocket all-I-care-about-is-how-many-frames-per-second-I-get consumer. Technology companies (especially all the big name brands) love the latter because they keep the cash rolling in.

I gladly acknowledge the importance of keeping the market flowing, but the proliferation of misinformation coming from such individuals is extremely damaging, especially to those of us who are engineers — we end up spending more time debunking, breaking down, and having to defend facts than if we were to simply provide good information from the get-go. But what people find on the Internet today is often speculative and en masse, and that disappoints me.