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.
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.