Flash drives enjoy a reputation for being fast and that certainly goes for high-end models with their elaborate memory controllers and multi-bank layouts. A fundamental “problem” with current flash memory technology is that writing even a single bit of information requires that an entire block of flash memory is reset first [1], which greatly reduces write performance.
People seem to notice that problem especially on Linux (please bother a search engine for sources or just default to [2]). While researching the cause and remedy I stumbled across a fundamentally interesting problem of what the proper filesystem setup for a flash drive might be and how it affects write performance.
The Linux How-To blog [3] spotted the problem long before I did and also provided an elaborate solution, which I think is remarkable for its details.
Of block sizes and file systems
[3] makes the case for a mismatch between flash memory block sizes and file system block sizes. Common file systems used for USB sticks such as FAT or ext2 have block sizes which are much smaller than the native flash memory block sizes. Thus, when the file system driver thinks it cleverly bundled multiple updates into a single write operation to a few blocks, in fact it is updating much larger blocks on the flash drive. Furthermore, partitioning tools will align file systems to 512 or 4096 byte block sizes, which might be a good choice for magnetic, rotational hard disks, but doesn’t align well with flash block sizes on USB sticks.
An important point to make which probably doesn’t hold for the high-end flash SATA disk, but most certainly goes for cheap USB sticks: the entire stick is locked down during (slow) write operations, queueing write and read operations behind them. Just go ahead and try a serial transfer with dd from a USB stick, run iostat in parallel and then once in a while write a few blocks to the USB stick: you’ll see that the read throughput reported by iostat drops dramatically.
Setting up a file system with larger blocks
The solution is to set up a file system with a larger block size and align it with the physical flash blocks.
I’m simply repeating the commands from [3] for setting up a USB stick on /dev/sdb with a block size of 128K:
fdisk -H 224 -S 56 /dev/sdb
mke2fs -t ext4 -E stripe-width=32 -m 0 /dev/sdb1
Resources
[1] Flash Memory
http://en.wikipedia.org/wiki/Flash_memory#Block_erasure
[2] Copy to USB memory stick really slow?
http://askubuntu.com/questions/122113/copy-to-usb-memory-stick-really-slow
[3] Increase USB Flash Drive Write Speed
http://linux-howto-guide.blogspot.com/2009/10/increase-usb-flash-drive-write-speed.html