SSD Raid Arrays unter Linux – IX – Chunk Size und Performance eines md-Raid-10-Arrays

In früheren Blogbeiträgen hatte ich mich Ende 2016 ein wenig mit SSD-Raid-Arrays unter Linux auseinandergesetzt:

SSD Raid Arrays unter Linux – I – ein facettenreiches Thema
SSD Raid Arrays unter Linux – II – Hardwarecontroller ?
SSD Raid Arrays unter Linux – III – SW- Raid vs. Intel-iRST-Raid – Performance?
SSD Raid Arrays unter Linux – IV – OS und Daten auf einem Raid-Array?
SSD Raid Arrays unter Linux – V – SW-Raid vs. iRST-Raid – Boot-Unterstützung?
SSD Raid Arrays unter Linux – VI – SW-Raid vs. iRST-Raid – Flexibilität?
SSD Raid Arrays unter Linux – VII – problematische Aspekte von Raid-5-Arrays
SSD Raid Arrays unter Linux – VIII – Setup von Raid-10-Arrays mit mdadm

Ich möchte in diesem Blog-Beitrag einige Performance-Daten für ein Raid-10-Setup mit SSDs nachreichen. Wir betrachten dabei ein SW-Raid-Array (md-Raid), dass mit Hilfe von “mdadm” erstellt wurde. Die Daten, die auf einem Opensuse-System gewonnen wurden, unterstreichen den großen Einfluss der “Chunk-Size” auf einige Einsatzszenarien. Wichtigstes Ergebnis:

Man kann nicht grundsätzlich davon ausgehen, dass eine große Chunk-Size (≥ 512 KB) die beste Performance liefern wird.

Test-Voraussetzungen

Die Voraussetzungen für die nachfolgend ermittelten Daten waren:

Raid-Array:
Linux SW-Raid-10-Array aus 4 SSDs (Samsung EVO 850); Near N2-Layout. Verwendete Partitionsgrößen auf den SSDs: 40 GiB. Das Array wurde z.B. für eine Chunk Size von 32kiB z.B. erzeugt mit

 
mdadm --create --verbose /dev/md/d02 --level=raid10 --bitmap=none --chunk=32 
--layout=n2 --raid-devices=4 /dev/sda5 /dev/sdb5 /dev/sdc5 /dev/sdd5 

Eine “Bitmap” (s. hierzu den letzten Artikel) wurde also nicht angelegt. Für die “Chunk Size” wurden test-abhängig Werte von 8k, 16k, 32k, 512k verwendet. Vor jedem Einzeltest wurde ein fstrim-Befehl auf die zu testende Partition des Raid-Systems abgesetzt. Hinsichtlich der Schreibtests lagen also optimale Voraussetzungen vor. Es wurden LVM2 Logical Volumes verwendet, die mit einem “ext4”-Fielssystem versehen wurden. Der LVM- und Filesystem-Overhead gegenüber einem Schreiben mit dem Tool “fio” (s.u.) auf unformatierte Partitionen erwies sich als unerheblich.

OS und HW:
Opensuse Leap 42.1 mit Kernel 4.1; i7 6700K; Onboard Z170 Intel Raid-Controller (Kernel-Modul: pinctrl_sunrisepoint). Scheduler: Deadline.
Die Kernelversion ist leider wichtiger als man meinen möchte. Die nachfolgend ermittelten Daten lassen sich z.B. auf einem System mit Opensuse Leap 42.2 mit Kernelversion 4.4 nicht erzielen! Bei gleichem Setup, gleicher FIO-Version und identischem HW-Unterbau ist die Performance zum Teil deutlich schlechter. Für Einzelprozesse und Daten-Paket-Gößen unterhalb 1 MB waren auf derselben HW-Plattform Perfromance-Einbrüch von 25 bis zu 30 % zu verzeichnen.
Unverständlicherweise! Im asymptotischen Bereich (große Daten-Pakete, die die Chunk Size weit übersteigen und/oder viele parallel arbeitende Jobs) werden aber die gleichen Werte wie unter einem 4.1 Kernel erreicht. Vorläufige Untersuchungen zeigen, dass die schlechtere Performance ein Effekt ist, der schon bei Einzel-SSDs auftritt und durch das Raid10-System nur noch verstärkt wird.

Test-SW und Datenstruktur:
Ich habe primär “fio” in der Version 2.2.10 und für sequentielles Lesen/Schreiben großer Datenpakete ergänzend auch “gnome-disks” eingesetzt. Es wurden Daten von insgesamt 500 MB Größe geschrieben. Unter “fio” galten dabei besondere Bedingungen: Die Nutzung des Linux-Caches wurde durch Optionen umgangen; wir wollen ja die tatsächliche Raid-Performance testen. Typische Einstellungen für die FIO-Jobs waren in etwa solche wie nachfolgend für einen “Random Write”-Job angegeben:

[global]
size=500m
direct=1
bs=64k
ioengine=sync

[write]
bs=64k
numjobs=1
rw=randwrite

Die fio-Blocksize “bs” wurde im Test zwischen 8k und 20000k variiert – damit wurde im Test abgefragt, wie das System auf unterschiedliche strukturiertes Datenaufkommen reagiert: Kleine einzelne Datenpakete (spike-artig) vs. größere Datenpakete (etwa größere Files).

Nur 1 Job liest oder schreibt auf das Array:
Von großer Bedeutung für die Testergebnisse ist die fio-Einstellung, dass nur genau ein (1) Job zu einem Zeitpunkt ein Datenpaket lesen oder schreiben soll. Die Ergebnisse würden sich drastisch ändern, wenn mehrere Jobs gleichzeitig auf das Raid-System zugreifen würden. Im Besonderen würde die Schreibperformance bei “Random Write”-Tests deutlich nach oben gehen. Damit wird sich ein kommender Artikel befassen.

Man kann in etwa sagen, dass eine zunehmende Zahl von Jobs einen ähnlichen Effekt hat wie eine deutliche Vergrößerung der Größe “bs”: Es stehen zu einem Zeitpunkt immer viele Datenblöcke, die über Chunks möglichst parallel auf die Platten geschrieben werden. Die Chunksize wird dann einfach früher und trotz evtl. kleiner “bs”-Werte überschritten.

Schwankungsbandbreite
Die Ergebnisse zu den Transferraten haben eine Schwankungsbandbreite zwischen 8 und 25 MB/sec. Tendenziell ist die Schwankungsbreite bei kleinen Datenpaketgrößen höher. Das liegt u.a. auch an der sonstigen Auslastung des Testsystems. Ich habe versucht, so viele Prozesse wie möglich abzuschalten; ferner wurde jede der durchgeführten Messungen 3 mal wiederholt. Es wurde ein sinnvoller Mittelwert bei leichter Bevorzugung hoher Werte angegeben.

Daten

Die nachfolgende Tabelle ist wie folgt zu lesen:

Am Kopf der verschiedenen Testblöcke ist die Art des Lesen/Schreibens (Random vs. Sequential) angegeben.

  • Die Variation der “Chunk Size” entnimmt man der zweiten Spalte.
  • Es folgen pro Zeile mehrere Blöcke aus jeweils 2 (oder 3) zusammengehörigen Spalten mit der verwendeten fio-“bs” und dem zugehörigen Messwert für die Datentransferrate in MiB/s. Zu den mit “gdisk” bezeichneten Spalten s.u..
  • Die Zeilen mit SSD am Anfang zeigen Werte, die für eine einzelne SSD-Partition außerhalb des Raid-Verbunds gemessen wurden (Einzelzugriff auf eine SSD).
  • Die Spalten mit der Überschrift “gdisk” stehen für zusätzliche Werte, die mit dem Tool “gnome-disks” gewonnen wurden. Sie betreffen nur sequentielle Lese- und Schreibtests.

Grün markierte Werte markieren aus meiner Sicht akzeptable Werte; bei ihnen kommt auch die Performance-Verbesserung durch Einsatz eines
Raid-vebrunds gegenüber einer Einzel-SSD voll zum Tragen. Werte für sequentiell Zugriffe und eine Chunk Size von 16K habe ich leider noch nicht erhoben; sorry.

n

500M

                                     

Random Read

                           

gdisk

   

gdisk

 

chunk

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

MB/s

bs

MB/s

MB/s

SSD

8

64

16

126

32

200

64

278

128

327

512

433

1024

460

 

20000

497

 

R10_0

16

8

66

16

149

32

235

64

448

128

604

512

753

1024

832

 

20000

851

 

R10_1

32

8

66

16

128

32

215

64

390

128

720

512

791

1024

868

 

20000

932

 

R10_2

512

8

64

16

128

32

209

64

277

128

318

512

436

1024

851

 

20000

976

 
                                       

Random Write

                                     
 

chunk

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

MB/s

bs

MB/s

MB/s

SSD

8

166

16

243

32

409

64

457

128

458

512

478

1024

492

 

20000

502

 

R10_0

16

8

158

16

285

32

484

64

615

128

680

512

730

1024

775

 

20000

790

 

R10_1

32

8

166

16

295

32

384

64

609

128

731

512

754

1024

816

 

20000

850

 

R10_2

512

8

130

16

299

32

347

64

430

128

464

512

463

1024

837

 

20000

873

 
                                       

500M

                                     

Seq Read

                                   
 

chunk

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

MB/s

bs

MB/s

MB/s

SSD

8

 

16

371

32

425

64

480

128

483

512

493

1024

506

 

20000

517

 

R10_0

16

8

 

16

 

32

 

64

 

128

 

512

 

1024

 

986

20000

   

R10_1

32

8

 

16

355

32

432

64

796

128

724

512

773

1024

883

950

20000

980

1030

R10_2

512

8

 

16

354

32

425

64

472

128

495

512

485

1024

950

998

20000

1010

1100

                                       

Seq Write

                                     
 

chunk

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

bs

MB/s

MB/s

bs

MB/s

MB/s

SSD

8

 

16

333

32

410

64

456

128

485

512

484

1024

490

 

20000

502

 

R10_0

16

8

 

16

 

32

 

64

 

128

 

512

 

1024

 

380

20000

   

R10_1

32

8

 

16

298

32

377

64

647

128

734

512

756

1024

812

399

20000

850

840

R10_2

512

8

 

16

301

32

370

64

423

128

450

512

464

1024

836

374

20000

886

841

                                       

 

Interpretation

Wir kommen zu folgenden Ergebnissen und möglichen Erklärungen des festgestellten Verhaltens:

Feststellung 1: Besonders das Lesen kleiner Datenpakete liegt den Samsung SSDs nicht.

Erklärungsansatz: Typischer SSD-Leistungseinbruch bei kleinen Datenpaketen
Wir sollten nicht allzu sehr überrascht sein, wenn wir bei kleinen Datenpaketen einen generellen Performance-Verlust der SSDs feststellen. Dieses Verhalten ist schon bei Einzel-SSDs gegeben – und übrigens auch bei klassischen Harddisks nicht anders. Viele Leute sind sich dessen aber nicht bewusst; in der Werbung geben die Hersteller ja meist nur die sequentiell erreichbaren Maximalraten an. Diese Werte spiegeln aber das tatsächliche, im Mittel deutlich kleinere Leistungsvermögen bei kleinen Einzeldatenpaketen überhaupt nicht wieder. Der Fairness sei auch gesagt, dass HDDs im Bereich kleiner Datenpakete sehr viel schlechtere Werte zeigen.

Erklärungsansatz: Erwartbar stärkerer Einbruch der Lese- als der Schreibperformance bei kleinen Datenpaket-Größen
Offenbar ist es ein verbreitetes Phänomen, dass bei vielen SSDs für geringe Datenpaketgrößen die Leseperformance hinter der Schreibperformance zurückfällt. Siehe hierzu:
http://www.anandtech.com/show/6935/seagate-600-ssd-review/5
Ich habe leider keine Ahnung, wie das technisch zu begründen ist. Besseres Caching zu schreibender Daten auf dem internen SSD-Controller? Jedenfalls zeigen meine Daten genau diesen Effekt – z.T. mit einer überraschend großen Diskrepanz zwischen Lese- und Schreibperformance.

Feststellung 2: Erst wenn die Datenpaketgröße die “Chunk Size” (deutlich) übersteigt, hebt sich auch die Performance des Raid-10-Arrays deutlich gegenüber der einer einzelnen SSD ab.

Feststellung 3: Unterhalb einer Datenpaketgröße von 1MB wird auch bei Überschreiten der Chunk Size keine Verdoppelung der Performance gegenüber einer Einzel SSD erreicht.

Erklärungsansatz: Fundamentale Bedeutung der Chunk Size
In den vorhergehenden Blogbeiträgen hatte ich bereits diskutiert, dass die Chunk Size eine Mindestgröße angibt, ab der parallele Zugriffe auf die 2 Stripeset-Komponenten des Raid-10-Arrays überhaupt erst ermöglicht werden. Deshalb würde man für Situationen, in denen der “bs”-Wert – also die Größe des zu verarbeitenden Datenpakets – die Chunk Size unterschreitet, einen deutlichen Einbruch der Performance erwarten. Da das Raid-System auch Overhead verursacht, würde man bei kleinen Datenpaketen ggf. sogar damit rechnen, dass die Performance des Raid-Arrays die einer Einzel-SSD (also außerhalb des Raid-Verbunds) unterschreitet. Statistisch geschieht das tatsächlich; in der Tabelle kommt das durch eine leichte Bevorzugung besserer Werte aber nicht zum Tragen.

nFeststellung 3: Eine annähernde Verdoppelung der Leistung wird erst asymptotisch bei großen Datenpaketen erreicht. Das gilt für Random Read/Write wie für Sequential Read/Write. Im asymptotischen Bereich mit Datenpaketgrößen > 1MB sind auf einem Raid-10-Array mit Consumer-SSDs aber Schreibraten jenseits von 850 MB/sec und Leseraten jenseits von 1000 MB/sec möglich (SSD: EVO 850).

Erklärungsansatz: ???
Ehrlich gesagt, hier kann ich keine fundierte Erklärung liefern. Timing-Probleme des SSD-Controllers? Timing-Probleme zwischen Kernel, SW-Raid und dem Controller? Zusammenspiel interner SSD-Caches mit dem Test? Besonders erklärungsbedürftig scheint mir zu sein, dass beim sequentiellen Lesen sowie einer Chunk Sitze von 32 KB im Bereich von Datenpaket-Größen zwischen 64KB und 512 KB keine Systematik vorzuliegen scheint. Es wäre an dieser Stelle auch interessant zu sehen, wie sich eigentlich ein Raid-0-Array verhält.

Feststellung 4: Bei großen Datenpaketen nähern sich die Random-Raten den sequentiellen Raten an.

Erklärungsansatz: Asymptotik
Mit wachsender Größe der Datenpakete gibt man dem System die Möglichkeit, ein immer sequentielleres Verhalten zu erreichen.

Feststellung 5: gnome-disks liefert vor allem beim sequentiellen Schreiben von Datenpaketen mit 1MB Größe seltsame und gegenüber fio viel zu kleine Werte.

Erklärungsansatz: ???
Keine Ahnung. Hier stimmt jedenfalls irgendetwas nicht. Ich persönlich traue hier “gnome-disks” nicht.

Erstes Fazit

Auch wenn wir nicht alle Daten schlüssig erklären können, sind vier Befunde offenkundig:

  • Mit Hilfe eines Raid-10-Arrays kann man eine deutlich höhere Performance als mit Einzel-SSDs erreichen.
  • Eine theoretisch mögliche Verdoppelung von Datentransferraten wird nur asymptotisch für große Datenpakete und sequentielle Zugriffe erreicht.
  • Für Szenarien, in denen nur 1 Job zu einer Zeit Daten liest oder schreibt, hängt der mögliche Performance-Gewinn stark davon, ob die Größe der Datenpakete im Mittel die “Chunk Size” übersteigt oder nicht. Die richtige Wahl der “Chunk Size” ist vor allem dann wichtig, wenn regelmäßig einzelne kleine Datenpakete vom und zum Raid-10-Array transferiert werden müssen. Das kann z.B. für bestimmte Datenbank-Anwendungen relevant sein.
  • Eine Chunk Size von 32K stellt einen guten Kompromiss bzgl. der Unterstützung relativ kleiner Datenpaketgrößen und einer gleichzeitigen Performanceverbesserung gegenüber Einzel-SSDs dar.

Ausblick

Themen weiterer Artikel sollten Test für mehrere parallel lesende/schreibende Jobs, für andere Kernelversionen und auch für Raid-5-Arrays sein. Ich bitte diesbzgl. um etwas Geduld.

 

Opensuse 12.3-Upgrade – lvmetad-Warnung nach grub2-mkconfig

Ich bin ja gerade beim Upgraden diverser Seitensysteme (von Kunden wie im eigenen Netz) auf Opensuse Leap 42.2. Dabei kam mir auch ein unter KVM/qemu virtualisierter LAMP-Testserver unter Opensuse 12.3 unter die Finger. Beim Upgrade dieses KVM-Gastes waren zunächst die üblichen Hürden zu überwinden:
– Notwendige Abänderungen der Apache2-Konfiguration auf die aktuelle Syntax bzgl. des Zugangs zu Verzeichnissen (Wechsel zu Apache2-Versionen > 2.4)
– Manuelles Nacharbeiten des Upgrades der Mysql DB bzw. Maria DB zur Version 5.6 bzw. 10.0.30 mittels “mysql_upgrade -u root -p”.

Meldung zu lvmetad

Dann aber stolperte ich im Rahmen der Upgrades über eine mir bislang unbekannte Warnung im Zusammenhang mit der grub2-Konfiguration während der Upgrades:

/run/lvm/lvmetad.socket: connect failed: No such file or directory
WARNING: Failed to connect to lvmetad. Falling back to internal scanning.

Das verhinderte zwar keinen Neustart der Zwischenversionen Opensuse 13.1, 13.2 Leap 42.1; aber sauber erschien mir das dann doch nicht. Ein manueller Test unter Leap 42.2 mittels “grub2-mkconfig -o /boot/grub2/grub.cfg” ergab dieselbe Meldung.

Was ist lvmetad?

lvm2-lvmetad ist offenbar ein Caching-Service für Metadaten (“central metadata cache”), die aus physikalischen Volumes [PV] einer LVM-Volume-Group ausgelesen werden. Siehe hierzu:
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/metadatadaemon.html

Das Caching führt zu einer Beschleunigung der Ausführung von LVM bzw. LVM-Kommandos.

Dieser Service bzw. ein zugehöriger Socket sollten auf moderneren Opensuse-Systemen offenbar immer aktiviert sein. Ein Statuscheck auf von Scratch installierten Opensuse-Systemen der Versionen 13.1, 42.1, 42.2-Systemen ergab, dass diese Services/Sockets dort laufen – unabhängig davon, ob tatsächlich “Logical Volume Groups” und ” Logical Volumes [LV]” genutzt werden oder nicht.

Auf meinem alten 12.3-System waren die entsprechenden Services aber offenbar nicht aktiviert (“enabled”). (Oder aber der Upgrade hat da was verbockt.)

Dass ein laufender lvmetad-Dienst/Socket vorausgesetzt wird, gilt offenbar selbst dann, wenn das Opensuse-System – wie in meinem Fall – virtualisiert ist und selbst gar kein LV auf den vom Host per virtio-(blk)-Treiber durchgereichten Blockdevices nutzt (also auch kein sog. “nested” LVM für den Fall, dass das Blockdevice selbst auf einem LV des Hostes beruht).

Problemlösung: Aktivieren von lvmetad

Die Lösung war jedenfalls trivial; es half die Durchführung folgender Kommandos

systemctl enable lvm2-lvmetad.socket
systemctl enable lvm2-lvmetad.service
systemctl start lvm2-lvmetad.socket
systemctl start lvm2-lvmetad.service

auf dem von OS 12.3 auf Leap 42.2 upgegradetem System. Ein “grub2-mkconfig -o /boot/grub2/grub.cfg” lief danach ohne jede Warnung oder Fehlermeldung durch.

Fühlbare Performance-Vorteile habe ich auf dem unter KVM virtualisierten System erwartungsgemäß nicht feststellen können; das nutzt zwar ein LV einer LVM Volume Group des KVM-Hostes als Raw-Device über virtio-(blk)-Treiber. In dieser Situation ist es viel wichtiger, dass lvmetad auf dem KVM-Host selbst läuft.

Upgrade von Opensuse 13.1 auf Leap 42.X – falsche OS-Version in den Grub2-Einträgen

Beim längst überfälligen Upgrade zweier Systeme von Opensuse 13.1 auf Leap 42.2 ist mir aufgefallen, dass sich in den Grub2-Einträgen hartnäckig die Bezeichnung “Opensuse 13.1” hielt. Das galt für jeden der Zwischenschritte “OS 13.1 => OS 13.2 => Leap 42.1 => Leap 42.2”. Die Ursache hierfür war, dass es – aus welchen Gründen auch immer – während der ursprünglichen Installation von OS 13.1 zu einem festen Eintrag in der Datei “/etc/default/grub” gekommen war (zumindest bei meinen Systemen). Als entscheidend erwies sich dabei die Festlegung:

GRUB_DISTRIBUTOR=”Opensuse 13.1″

Der Upgrade-Vorgang rührt einen vorhandenen Eintrag offenbar nicht an.

Der Trick, um grub2 zu einer dynamischen Ermittlung der OS-Version zu bewegen, besteht darin, diesen Eintrag einfach leer zu lassen. Die OS-Information besorgt sich grub2 dann aus der Datei “/etc/os-release“. Hat man den OS-Upgrade-Vorgang mittels “zypper” gestaltet, findet sich dort die aktuelle OS-Info vor. Also im Editor

GRUB_DISTRIBUTOR=

setzen und die “/etc/default/grub” abspeichern. Abschließend ist die geänderte Grub2-Konfiguration mittels

myserver:~ # grub2-mkconfig -o /boot/grub2/grub.cfg

installieren. Beim nächsten Reboot passen die Einträge in der Grub2-Anzeige dann wieder.