Looking to remove one more speed bottleneck from your Raspberry Pi server? Me, too! That’s why I looked into SSD hard drive technology, specifically an M.2 drive, for my Raspberry Pi 4. The Pi4 has two USB3 sockets and I really wanted to take advantage of its interface speed. Those little blue sockets hold big secrets. Just take a look at how the speed has increased over the past few years!
USB Interface Speeds
|Data rate||1.5 Gb/s||1.5 Gb/s||5 Gb/s||10 Gb/s||20 Gb/s||40 Gb/s|
Let’s see if we can get some better read / write times out of that USB3. I’m tired of looking at top and seeing the “wa” (hard drive waiting times) posting such high numbers!
Hardware Used in this Test
WD_Black SN750 250GB M.2 2280 format drive from Western Digital. Geekworm recommended not using a Samsung…
Raspberry Pi 4 Model B (4GB model )
SanDisk 32GB Ultra microSDHC I buy these 5 at a time.
SanDisk Cruzer Fit 8 GB USB Flash Drive (buy these IN a 5 pack)
Here’s the Geekworm kit. Basically you get a board to clip the M.2 drive to, some standoffs, the USB3 coupler, and a screwdriver.
Assembly is simple. Use the standoffs to attach the boards and put the USB3 coupler in place. Slide the M.2 drive into place and use the flathead screw to hold it in place.
Boot it up and let’s see if it works:
root@node4-0:~# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 232.9G 0 disk └─sda1 8:1 0 232.9G 0 part /m2 sdb 8:16 1 7.5G 0 disk └─sdb1 8:17 1 7.5G 0 part /thumb mmcblk0 179:0 0 29.7G 0 disk ├─mmcblk0p1 179:1 0 256M 0 part /boot └─mmcblk0p2 179:2 0 29.5G 0 part /
Ahhh! It’s so nice when things work the first time! sda is the M.2 drive on the Geekworm board. sdb is a Sandisk 8Gb thumb drive. mmcblk0 is the SD card.
Here’s a different view:
root@node4-0:~# lsusb Bus 002 Device 002: ID 152d:0562 JMicron Technology Corp. / JMicron USA Technology Corp. Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 003: ID 0781:5571 SanDisk Corp. Cruzer Fit Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub root@node4-0:~#
Here you can see the M.2 interface board, the thumb drive and SD card. Let’s see if we can partition the M.2 drive. I’ve been using parted. I like it because you can tell 100% for the end of the partition to use the whole drive. I hate trying to figure out the math.
M.2 drive Configuration
root@node4-0:~# parted GNU Parted 3.2 Using /dev/sda Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) mklabel gpt (parted) mkpart Partition name? ? m2 File system type? [ext2]? ext4 Start? 1 End? 100% (parted) quit Information: You may need to update /etc/fstab. root@node4-0:~# mkfs /dev/sda1 mke2fs 1.44.5 (15-Dec-2018) Creating filesystem with 61049344 4k blocks and 15269888 inodes Filesystem UUID: 341e5082-773e-4ee6-b6e4-41a80c304ac5 Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 4096000, 7962624, 11239424, 20480000, 23887872 Allocating group tables: done Writing inode tables: done Writing superblocks and filesystem accounting information: done
Mount it and check it:
root@node4-0:~# mount /dev/sda1 /mnt root@node4-0:~# df -h Filesystem Size Used Avail Use% Mounted on /dev/root 29G 3.1G 25G 12% / devtmpfs 1.8G 0 1.8G 0% /dev tmpfs 1.9G 20K 1.9G 1% /dev/shm tmpfs 1.9G 492K 1.9G 1% /run tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup /dev/mmcblk0p1 253M 54M 199M 22% /boot tmpfs 380M 0 380M 0% /run/user/1000 tmpfs 380M 0 380M 0% /run/user/0 /dev/sda1 230G 60M 218G 1% /mnt
OK. It really works! I’m dying to speed test this thing in comparison to the SD card and the thumb drive. Let’s set up three directories, each one on a different media:
root@node4-0:~# mkdir /m2 root@node4-0:~# mkdir /thumb root@node4-0:~# mkdir /sdcard root@node4-0:~# mount /dev/sda1 /m2 root@node4-0:~# mount /dev/sdb1 /thumb
Let’s use dd’s “direct mode” to test the three mounted media. I mounted the M.2 drive to /m2. I mounted the thumb drive to /thumb and the SD card is the root drive, so I just created a directory “/sdcard” to represent the SD card. I’ll issue a dd to copy from the zero “device” to each of the mount points. The combination of command line arguments will create a 2GB file on each device and we can analyze the results in the dd standard out.
First the SD card:
root@node4-0:~# dd if=/dev/zero of=/sdcard/2G_test_file.txt oflag=direct bs=128k count=16k 16384+0 records in 16384+0 records out 2147483648 bytes (2.1 GB, 2.0 GiB) copied, 170.724 s, 12.6 MB/s
That last number, 12.6 MB/s is our baseline. Nothing to write home about. Next, the thumb drive:
root@node4-0:~# dd if=/dev/zero of=/thumb/2G_test_file.txt oflag=direct bs=128k count=16k 16384+0 records in 16384+0 records out 2147483648 bytes (2.1 GB, 2.0 GiB) copied, 596.521 s, 3.6 MB/s
3.6 MB/s!?!? We’re going in the wrong direction. Actually, this is no surprise. I always tell people that you trade speed for reliability when you go from SD card to thumb drive. Finally, let’s hit our fancy new M.2:
root@node4-0:~# dd if=/dev/zero of=/m2/2G_test_file.txt oflag=direct bs=128k count=16k 16384+0 records in 16384+0 records out 2147483648 bytes (2.1 GB, 2.0 GiB) copied, 16.4942 s, 130 MB/s root@node4-0:~#
The Big Winner
130MB/s! Hell, yeah! That’s what I’m talking about! Thanks, Geekworm! Awesome product! Time to get my Minecraft world file copied over to my new drive!!
Update: 6/4/21 = Better Way!
There’s a better way to do this!! I’m working on rebuilding this Raspberry and was having trouble booting with a freshly imaged USB drive. Then, when I tried booting from SD, the m.2 wasn’t always appearing. So, I pulled the m.2 sled off, plugged in the USB U-shaped connector and plugged a USB extension cable into that and then plugged that into my computer and imaged the whole thing with balena Etcher. Put the Raspberry back together and it booted right up! No transfering files, boot partitions, and waiting for the USB bus to setting so the damn thing would boot!