MicroSD performance on memory-constrained devices

Sjors de Wit
July 31, 2019
Last updated: Feb 29, 2020

MicroSD cards. They are used in phones, cameras and all kinds of devices. A no-brainer to add some extra storage capacity to your project. They are advertised by their average read/write speed in MB/s. But there is a metric that is at least as important for certain applications: latency…

Memory-constrained applications

Modern devices like smartphones have plenty of memory. When you take a video, it is no problem to buffer a few seconds of data in memory while processing it in the background. As long as the average write speed can keep up with the video feed, this works perfectly.

Embedded devices are different. Microcontrollers don’t have a lot of memory and tend to work with realtime data: a stream of data coming from some sensors that need to be saved right away: no memory available to buffer it for a long time. This is where latency becomes an important factor. If it takes too long to write a block of data to the SD card, the next batch of fresh sensor data has no where to go.

Write Latency

Unfortunately, MicroSD write speed is not constant. Most of the writes are pretty fast, but once in a while, the card will be ‘busy’ for some time before allowing a new write. This presents a challenge: while the SD card is busy, you need to buffer the incoming data from e.g. your sensors in memory.

We want to guarantee that our program always has enough time to write its data.
So how long does an SD card stay busy? What is the worst-case time to write a block of data? And how much memory do we need?

Benchmark

Manufacturers of MicroSD cards generally don’t publish useful statistics about the maximum write latency. Even the more expensive industrial-grade cards don’t explicitly state these. So let’s run some tests! Our test set consists of 7 different MicroSD Cards. Some of the cheapest 8GB consumer cards and three more expensive Industrial-rated MicroSD cards.

We are using the blinky101 lpc43xx development board, which we have developed as part of our blinky101 project. This is a dev board for the LPC43xx, a microcontroller with a built-in SDMMC peripheral.

The benchmarks were done by writing to a file in a FAT filesystem. While the filesystem may carry some overhead, we wanted to keep the benchmark as closely as possible to our actual use case.

Block size 512

512 Bytes is the block size of the FAT filesystem, so let’s assume this is the minimum amount of data to write if we want any kind of performance.

Naive implementation

Open a file, append 512 bytes, close the file, repeat. This is convenient but may carry some filesystem-related overhead. This test writes an 8MB file.

MicroSD Card Max block latency (ms) Guaranteed throughput (KB/s) Avg throughput (KB/s)
Team (8GB, class 10) 130 3.9 18.7
Sandisk Edge (8GB, class 4) 340 1.5 148.4
Kingston (8GB, class 10) 381 1.3 32.5
Toshiba (8GB, class 4) 204 2.5 58.5
Panasonic (1GB, SLC) 63 8.1 48.4
Apacer Industrial (1GB, SLC) 20 25.6 100.2
Sandisk Industrial (8GB) 24 21.3 112.3

As can be seen, the results are rather terrible. The first four cards all have worst-case write times (which we call Max block latency) well above 100ms! A 512-byte block taking up to 200ms means you cannot process more than 2.5KB/s reliably! This is what we will call Guaranteed throughput: the maximum speed of a real-time data stream that we can write without dropping bits on the floor.
Note how the average throughput (if you had no realtime requirements at all) is an order of magnitude faster.

Faster implementation

OK, maybe re-opening a file for each write is a bit silly. Let’s repeat the test, but just open a file once and write 8MB to it in blocks of 512. Surely that is a lot faster?

MicroSD Card Max block latency (ms) Guaranteed throughput (KB/s) Avg throughput (KB/s)
Team (8GB, class 10) 170 3.0 114.0
Sandisk Edge (8GB, class 4) 211 2.4 436.2
Kingston (8GB, class 10) 156 3.3 228.2
Toshiba (8GB, class 4) 113 4.5 178.5
Panasonic (1GB, SLC) 53 9.7 402.1
Apacer Industrial (1GB, SLC) 21 24.4 378.4
Sandisk Industrial (8GB) 15 34.1 390.9

The numbers have improved, but the gap between Guaranteed and Average throughput is growing. The last three (industrial-grade) cards in the table clearly perform much better than the first four (consumer-grade). The write latency on consumer-grade cards also varies significantly when running the same test twice, while the industrial cards seem fairly stable.

Block size 2048

Let’s increase the buffer size to 2KiB and the total data transfer to 32MiB. 2KiB of memory should not be a problem to allocate on a modern microcontroller.

MicroSD Card Max block latency (ms) Guaranteed throughput (KB/s) Avg throughput (KB/s)
Team (8GB, class 10) 113 18 386
Sandisk Edge (8GB, class 4) 151 14 1169
Kingston (8GB, class 10) 526 4 363
Toshiba (8GB, class 4) 448 5 371
Panasonic (1GB, SLC) 54 38 968
Apacer Industrial (1GB, SLC) 15 137 1334
Sandisk Industrial (8GB) 16 128 1148

The Apacer and Sandisk Industrial cards seem promising. The worst-case time to write a 2048-byte block is roughly the same as for writing a 512-byte block! For Toshiba and Kingston, increasing the block size does not seem to help. Team and Sandisk Edge do better, but their Guaranteed throughput is still no match for the industrial-grade cards.

Even Larger Block Sizes

Generally, the average performance increases when increasing the block size. The worst-case write-latency for industrial-grade cards is pretty constant. On the contrary, for the consumer-grade cards that we tested, the latency is more random and there is not a clear upper bound.

Latency vs time

We were curious to see the pattern behind these seemingly random latency spikes. Below are the plots of the latency for each block written for some of the SD cards.

Each MicroSD behaves distinctly different. Just by looking at the latency plots, you could identify which specific MicroSD was tested. The industrial cards tend to have a mostly regular pattern, while the consumer-grade cards seem to have very random spikes up to several hundreds of ms.

Conclusion

When writing realtime data to a MicroSD card, be sure to take into account how much RAM you need to smooth out the write latencies. If it is withing the budget, use an industrial-grade card: their performance is significantly better and more consistent.

Want to Reproduce?

The firmware for this benchmark is available as one of the example projects. The hardware design for our development board is available as part of our blinky101 lpc43xx repository. Any other LPC43xx-based board will probably work just fine.