At the request of a customer in the banking machines segment, Datalight recently completed an investigation of some performance differences they were seeing between SD and SSD on their embedded target. The findings left us scratching our head a bit. On the surface, SSDs and SDs have some things in common (beyond having S and D in their names) but many differences as well. Both media types are NAND based, but SD cards tend to be small and have fewer resources on-board than do their SSD cousins. The interface to the system is also quite different as most SSDs communicate via the faster SATA interface. So, the specs say that SSDs are faster than SD. And yet in our investigation, we found many use cases where SSDs were actually slower. In some performance tests we have done, we can see that comparing SDs and SSDs does not really seem to be fair: When looking at just the numbers, SD cards seem to be up to 10x faster than SSD when it comes to writing under some conditions – and that initially surprised us. Let’s talk about what we saw, and what it means to you - the user of such devices.
While we do want to share what we saw, there is a big caveat – our investigation thus far has been limited in scope, running under Microsoft Windows Embedded Compact 2013, and Wind River’s VxWorks 7.0. Although we tested cards/drives from more than one manufacturer during our testing, the number of brands was limited. Still, the information was interesting enough to us that we thought you might be interested in it too.
In these complex environments, the path taken by data from application to media can be convoluted, passing through caches and buffers at different layers of the system in an effort to improve or maintain performance. With our focus on data integrity, we seek to find the configuration that ensures complete commitment of the data to the media when a Reliance Nitro transaction point is called.
When Reliance Nitro does a transaction point, a command is issued through the operating system API to force any data that still resides in any caches (both OS, and hardware, if present) to be flushed to the media, and in this testing, this procedure is noticeably slower on SSD drives than it is on SD drives.
In Reliance Nitro, the simple test application we were using invoked the Windows CE APIs CloseHandle(), and FlushFileBuffers(), and these APIs will cause a Reliance Nitro transaction to occur if the transaction mask for the given disk is set to transact on "Close" or "Flush", respectively. At the end of all our transaction processing, Reliance Nitro calls the Windows CE API FSDMGR_CachedWrite(), which commits all data and metadata to the disk, flushing them out of any caches.
For the sake of comparison, we also tested exFAT on both SD, and SSD media, and it appears that exFAT, in its normal course of operation, does not make the same sort of calls that Reliance Nitro does to ensure that the data is getting pushed all the way out of all caches, and down onto the media.
We did an experiment where we removed power to the target system, after a manual file copy reported that it was complete when using exFAT as the file system. In one case, the copied file was shorter than the original, indicating that exFAT did *not* completely commit all data to the disk before power was removed, even though it said it did (by returning that it was finished). In other cases, the file sizes were equal, but the file contents did not compare (and this would be seen as data corruption to the end user).
As an additional experiment, we also tested TexFAT (which can be configured to "write through" to ensure data gets committed to the disk), and found that the behavior pattern of TexFAT was similar to that of Reliance Nitro: On SDs, it was (compared to itself) faster to commit data than on SSDs - here are some example numbers from our simple test showing the type of differences being seen - The numbers show below for each entry are the timing in milliseconds for each of the four following operations done in the test during the write testing:
|Texfat on an SSD|
|Texfat on an SD Card|
Note that on SSDs, the timing for CreateFile(), and WriteFile() were much higher than the timings done on the SD card.
When digging into this further, we noted on the SSD, the Windows CE API FSDMGR_CachedWrite() is actually doing something (flushing data out of a cache internal to the SSD, most likely), whereas on SD - it does no additional work (since SD has no internal cache), and so when timing the total time it takes to write to these two types of media, SD appears "faster". There may be configurations you can use in your system to control when and how data is committed to the media, which can help control when these flushes of data out of the caches and all the way down to the disk occur – but you must do so with the goals you have for data integrity/data-at-risk vs performance in mind.
At some point, your data must be committed to the media. If you value reliability and have chosen an SSD as a media you wish to use for data storage, then you need to understand that reliable file systems (like Reliance Nitro) will need to truly commit the data all the way to the media at some point, and that transactions takes more time the more caches that are in the system. Fortunately, with Reliance Nitro, you have the ability to configure when to transact - you could do so in a timed fashion, only when closing a file or after a series of files have been written - so you are in control.
We used a few example configurations of Reliance Nitro, and ran a performance test to show how changing the transaction mask could change the perceived performance of the test. This set of numbers below are just a representation of the data we collected, but you'll get the idea. The test was the same one displayed above for TexFAT, with the four numbers showing the timing in milliseconds of the four test calls of Createfile(), WriteFile(), FlushFileBuffers(), and CloseHandle().
With Reliance Nitro configured to transact on file close, and no timed transactions, we saw numbers like this: Write 1,6,0,956
|Reliance Nitro on SSD||Createfile()||WriteFile()||FlushFileBuffers()||CloseHandle()|
|Transact on file close||1||6||0||956|
|Timed transactions, 1 sec*||1||3||0||0|
|Transaction on flush||4||4||955||1|
Adjusting the Reliance Nitro Transaction mask to use timed transactions to fire every 1 second, we saw: Write 1,3,0,0
Note that these numbers look better, because the transaction occurs outside of the application’s measurement window).
When we set Reliance Nitro to again not used timed transactions, but rather transact on Flush alone, we saw: Write 0,4,955,1
Experimenting with different transaction settings, you can determine what settings work best for your use case. No one setting works for everyone, but this is why the flexibility of Reliance Nitro is so important - it gives you the ability to configure our file system to fit your needs.