Mit FIO die Leistung einer RAMDISK bewerten

Wie im Blogpost zu den FIO Grundlagen erläutert, ist FIO ein Open Source Werkzeug mit dem die I/O Leistung von Speichermedien mit unterschiedlichen Lastprofilen gemessen werden kann.

Baseline für Shared Storage in einem 10G Netzwerk

Um die I/O Leistung von Shared Storage (z.B. Synology, TrueNAS, OpenMediaVault oder Unraid) in einem 10 Gbit (10G) Netzwerk zu testen, braucht es sehr schnellen Speicher (Storage). Das kann aktuell (Dezember 2021) z.B. eine NVME Gen4 SSD an einem PCIe v4 bus mit einer theoretischen Bandbreite von gut 5 GB/s sein, oder eben eine RAMDISK im Speicher des Shared Storage Server sein.

Zu beachten ist, dass die maximale theoretische Bandbreite in einem 10 Gigabit pro Sekunde (Gbit/s oder Gbps) Netzwerk bei knapp 1,25 Gbyte/s liegt.

In meinem Playlab verwende ich zwei identische DELL Optiplex 9010 SFF (i5-3550, 32GB RAM) mit zwei SSDs (sda ist eine Intel SSD DC S3700 100GB und sdb eine Samsung SSD 860 EVO 500GB SSD).

In einem späteren Beitrag geht es dann darum, in einem 10 Gbit Netzwerk die I/O Leistung beim Zugriff eines Clients (H01, h01.myplaylab.net, 10.10.70.71) auf eine NFS Freigabe des Shared Storage Server (H02, h02.myplaylab.net, 10.10.70.72) mit der lokalen I/O Leistung zu vergleichen.

In diesem Beitrag geht es aber erst einmal darum, die lokale I/O Leistung einer RAMDISK auf H02 zu ermitteln.

RAMDISK als Block Device

Um unter Debian eine RAMDISK anzulegen gibt es mehrere Möglichkeiten und eine tmpfs RAMDISK anzulegen ist die einfachste davon. Allerdings brauche ich für den Test mit FIO ein Block Device, daher verwende ich das Kernelmodul brd.

1. RAMDISK anlegen

Im Test variiere ich die Anzahl der parallelen FIO Prozesse (parallele Schreib-/Lesevorgänge), so dass ich bei einer Größe der Testdateien von 4GB mindestens 16GB benötige, um Platz für 4 parallele FIO Prozesse zu haben.

Soweit notwendig kann zunächst geprüft werden, ob bereits eine RAMDISK angelegt ist.

ls -l /dev/ram*

Anschließend kann eine RAMDISK (rd_nr=1) in /dev/ram0 mit einer Größe von 20GB angelegt werden (rd_size in kilobyte, daher mit $(( ... )) auf der Shell berechnet). Mit der RAMDISK kann ein echtes ext4 Dateisystem verwendet werden und die Größe der RAMDISK kann nicht überschritten werden (auch nicht durch die Auslagerung in swap).

modprobe brd rd_nr=1 rd_size=$((20 * 1048576))
mkfs.ext4 /dev/ram0

Die RAMDISK kann nun gemountet werden

mkdir /mnt/ramdisk
mount /dev/ram0 /mnt/ramdisk

2. RAMDISK löschen

Die RAMDISK wird mit dem nächsten Neustart oder manuel durch das Entfernen des Kernelmoduls brd gelöscht. In beiden Fällen gehen alle auf der RAMDISK gespeicherten Daten verloren.

umount /dev/ram0
modprobe -r brd

3. Sequentielle Schreibvorgänge mit 4M Blocksize testen

sudo sync;fio --name=fiotest --ioengine=libaio --direct=1 --randrepeat=1 --group_reporting \
--fallocate=none --ramp_time=10 --iodepth=64 --loops=50 --size=4G --numjobs=1 \
--rw=write --bs=4M
fio: (g=0): rw=write, bs=(R) 4096KiB-4096KiB, (W) 4096KiB-4096KiB, (T) 4096KiB-4096KiB, ioengine=libaio, iodepth=64
fio-3.28
Starting 1 process

fio: (groupid=0, jobs=1): err= 0: pid=7526: Tue Dec 14 14:32:57 2021
  write: IOPS=1364, BW=5469MiB/s (5734MB/s)(147GiB/27528msec); 0 zone resets
    slat (usec): min=643, max=887, avg=725.83, stdev=21.07
    clat (usec): min=4, max=48726, avg=44711.09, stdev=6548.63
     lat (usec): min=685, max=49458, avg=45437.67, stdev=6548.40
    clat percentiles (usec):
     |  1.00th=[ 7308],  5.00th=[36963], 10.00th=[45876], 20.00th=[45876],
     | 30.00th=[45876], 40.00th=[45876], 50.00th=[46400], 60.00th=[46400],
     | 70.00th=[46400], 80.00th=[46400], 90.00th=[46400], 95.00th=[46400],
     | 99.00th=[46924], 99.50th=[46924], 99.90th=[48497], 99.95th=[48497],
     | 99.99th=[48497]
   bw (  MiB/s): min= 5392, max= 5480, per=99.88%, avg=5462.13, stdev=13.96, samples=55
   iops        : min= 1348, max= 1370, avg=1365.35, stdev= 3.51, samples=55
  lat (usec)   : 10=0.10%, 20=0.01%, 750=0.05%, 1000=0.05%
  lat (msec)   : 2=0.10%, 4=0.30%, 10=0.79%, 20=1.38%, 50=97.41%
  cpu          : usr=18.73%, sys=81.26%, ctx=16, majf=0, minf=58
  IO depths    : 1=0.1%, 2=0.2%, 4=0.4%, 8=0.8%, 16=1.5%, 32=3.1%, >=64=94.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=99.9%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
     issued rwts: total=0,37572,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=64

Run status group 0 (all jobs):
  WRITE: bw=5469MiB/s (5734MB/s), 5469MiB/s-5469MiB/s (5734MB/s-5734MB/s), io=147GiB (158GB), run=27528-27528msec

Disk stats (read/write):
  ram0: ios=0/0, merge=0/0, ticks=0/0, in_queue=0, util=0.00%
  ram0: ios=0/0, merge=0/0, ticks=0/0, in_queue=0, util=0.00%

FIO hat 147 GiB in knapp 28 Sekunden geschrieben. Das entspricht einer Bandbreite von 5469 MiB/s (5734 MB/s oder gut 5,7 GB/s) und 1364 IOPS bei eine I/O Blockgröße von 4MiB.

Der gleiche Test mit einer I/O Blockgröße von 4k ergibt eine Bandbreite von 1156 MiB/s (1212 MB/s oder 1,2 GB/s) und 296000 IOPS.

4. Bandbreite und IOPS in Abhängigkeit von Blockgröße

Die Diagramme zeigen für H02 die Ergebnisse der sequentiellen und zufälligen I/O Schreib- und Lesevorgänge in Abhängigkeit von der I/O Blockgröße. Zu besseren Lesbarkeit sind die IOPS logarithmisch dargestellt.

Die Ergebnisse für Schreib- und Lesevorgänge liegen bei der RAMDISK relativ eng zusammen. Sequente Lesevorgänge mit 4k blocksize liegen im Mittel bei 1424 MB/s mit 347000 IOPS und zufällige Lesevorgänge bei 1188 MB/s mit 290000 IOPS. Mit zunehmender Blockgröße nimmt die Bandbreite zu, während die IOPS abnehmen.

Ab ca. 64k steigt die I/O Leistung nicht mehr so stark an.

5. Bandbreite in Abhängigkeit von parallelen Schreib- und Lesevorgängen

Mit mehreren parallelen Schreib- und Lesevorgängen kann die maximal mögliche Bandbreite ausgetestet werden. Der Parameter numjobs legt dabei die Anzahl an Prozessen fest, die jeweils den definierten Workload erzeugen (Standardwert 1). Mit einer RAMDISK von 20GB und einer 4GB großen Testdatei sind als maximal 4 parallele Prozesse möglich, die mindestens 16GB Platz benötigen.

Bei vier parallelen Prozessen liegt die I/O Leistung sequentielle Lesevorgänge mit einer blocksize von 16k im Mittel bei 10700 MB/s mit 668000 IOPS und zufällige Lesevorgänge bei 10100 MB/s mit 618000 IOPS.

Allerdings ist der DELL Optiplex 9010 SFF bei zwei und erst recht bei vier parallelen Prozessen schon sehr stark ausgelastet. Alle verfügbaren CPUs sind zu 100% ausgelastet und die 1min, 5min und 15min load average liegt während der Tests dauerhaft knapp bei fast 4.

Während des Tests mit vier parallelen Schreib-/Lesevorgängen sind alle CPUs zu 100% ausgelastet. An der Speicherauslastung Mem kann man gut die 16G der 4x4GB Testdateien auf der RAMDISK erkennen.