Benchmarking SD card access

Put the code below in code.py on your CIRCUITPY drive, open up the REPL (and restart it with ^D if necessary) to get report of how quickly CircuitPython can read and write your SD card.

This example will work on any board where you've configured mount_sd.py!.

We saw some great speed increases going from good (adafruit_sdcard) to better (sdcardio) to best (sdio).  However, every SD card is different and (especially when writing data) slow down as they "age", so your mileage may vary:

  • SD card access with adafruit_sdcard on Grand Central:
    • Reads up to 120kB/s
    • Data logging at up to 160 of lines per second
  • SD card access with sdcardio on Grand Central:
    • Reads up to 650kB/s
    • Data logging at up to 700 of lines per second
  • SD card access with sdioio on Grand Central with SDIO breakout:
    • Reads up to 1100kB/s
    • Data logging at over 1000 lines per second
import time
import os

import mount_sd

# First, just write the file 'hello.txt' to the card
with open("/sd/hello.txt", "w") as f: print("hello world", file=f)

print()
print("SD card I/O benchmarks")

# Test read and write speed in several scenarios:
#  * 512 or 4096 bytes at a time
#  * Writing 1 time or 16 times
# First write the content to the SD card, then read it back, reporting the
# time taken.
for sz in 512, 4096:
    b = bytearray(sz)
    for i in range(sz): b[i] = 0xaa
    for n in (1, 16):
        with open("/sd/hello.bin", "wb") as f:
            t0 = time.monotonic_ns()
            for i in range(n):
                f.write(b)
            t1 = time.monotonic_ns()

        dt = (t1-t0) / 1e9
        print(f"write {len(b)} x {n} in {dt}s {n * len(b) / dt / 1000:.1f}Kb/s")

        with open("/sd/hello.bin", "rb") as f:
            t0 = time.monotonic_ns()
            for i in range(n):
                f.readinto(b)
            t1 = time.monotonic_ns()

        dt = (t1-t0) / 1e9

        print(f"read  {len(b)} x {n} in {dt}s {n * len(b) / dt / 1000:.1f}Kb/s")
        print()

# Test "logging" speed and report the time to write each line.
# Note that in this test the file is not closed or flushed after each
# line, so in the event of power loss some lines would be lost.  However,
# it allows much more frequent logging overall.
#
# If keeping data integrity is your highest concern, follow the logging
# example, not this logging benchmark!
print("logging test")
with open("/sd/log.txt", "wt") as logfile:
    t0 = time.monotonic_ns()
    for i in range(10000):
        t1 = time.monotonic_ns()
        dt = (t1-t0) / 1e9
        print(f"Line {i}, {dt:2f}s elapsed", file=logfile)
t1 = time.monotonic_ns()
dt = (t1-t0) / 1e9

print(f"Logged 10000 lines in {dt} seconds, {dt*100:.0f}us/line")
sz = os.stat('/sd/log.txt')[6]
print(f"{sz} bytes written, {sz/dt/1000:.1f}Kb/s")
This guide was first published on Jul 31, 2020. It was last updated on 2020-07-31 12:38:51 -0400.
This page (Benchmarking SD card access) was last updated on Jul 31, 2020.