Bald wird man sie kaufen können, die Non-Volatile Dual In-line Memory Modules. Elektrisch sind die schnellen Speicher wie RAM angebunden, behalten ihren Inhalt aber über Reboots hinaus. Der Linux-Kernel ist schon fit für die neue Technik und kann sie sogar als Blockgeräte anbieten.
Viele Datenbanken lassen sich so konfigurieren, dass sie vollständig im Hauptspeicher ihres Host liegen – Oracle Times Ten, Berkeley DB, Apache Derby oder MySQL-Cluster beispielsweise. SAP HANA ist sogar eine reine In-Memory-Datenbank. Solche Produkte sind im Einsatz, wenn es um schnelles Antwortverhalten trotz hoher Workloads geht. Auch das klassische High Performance Computing hält Arbeitsdaten gern in den Hauptspeichern der Knoten vor, damit die CPUs nicht zu lange auf Daten von Massenspeichern warten müssen.
Da der Inhalt des Hauptspeichers beim Shutdown oder Ausfällen stets verloren geht, müssen solche Systeme periodisch auf ein nicht-flüchtiges Medium rücksichern. Das funktioniert in der Praxis nicht besonders zuverlässig und bremst das ganze System zeitweise aus. Gut wäre es, einen RAM zu haben, der nicht-flüchtig ist. Ein solcher kommt demnächst auf den Markt: NV-DIMM. Vorbild waren Puffercache-Speicher auf Raid-Controllern, die beim Abschalten des Systems ihre Inhalte behielten, um die Integrität der zu schreibenden Daten zu gewährleisten.
Im Dezember 2015 hat das Subkomitee JC-45 des Industriegremiums Jedec [1] Spezifikationen für persistente Speichermodule veröffentlicht, die in die Fassung für DDR4-SDRAM-DIMMs passen. Motherboards brauchen jedoch ein Bios, das die Riegel unterstützt. Jedec sieht zwei Arten vor: NV-DIMM-N sichert bei Stromausfall den Inhalt seines DRAM in Flashbausteinen und stellt die Daten nach Rückkehr der Spannung wieder her. Ein NV-DIMM-F hingegen verhält sich ähnlich einer SSD, die am Speicherbus hängt.
Hilfreiches Zwitterwesen
So ein Non-Volatile-DIMM ist ein Wanderer zwischen beiden Welten. Im Erscheinungsbild leicht mit einem normaler DDR4-Speicherriegel zu verwechseln, nur ein (oft größerer) Stützkondensator, manchmal Akkus und ein Flashchip verraten die fremdartige Funktionen. Muss der Admin den Server herunterfahren, puffern die Kondensatoren oder Akkus den Inhalt des Riegels so lange, bis er komplett auf den verbauten Flashchip geschrieben ist. Neuere Technologien versprechen auch diesen Schritt einzusparen, indem sie direkt den Flash schnell genug machen, um ihn direkt als Hauptspeicher nutzen zu können.
Der typische Einsatzort für NV-DIMMs sind die angesprochenen In-Memory-Datenbanken, aber auch das High Performance Computing. Hierfür haben Linux-Entwickler den Kernel angepasst und DMA-Transfers von und nach NV-DIMM ermöglicht – um etwa über Infiniband schneller Daten innerhalb eines Clusters auszutauschen.
Nicht jedes Datacenter unterliegt aber der Anforderung, mehrere Terabyte große Datenbanken im Speicher zu halten oder das Volumen unterirdischer Gasvorkommen zu berechnen. Trotzdem können NV-DIMMs auch bei Setups helfen, die schlicht Storage-Caching mit Hilfe von Bcache oder Dm-Cache ausführen wollen. Dann dient die NV-DIMM-Hardware als schneller und sicherer Puffer zwischen dem im RAM liegenden Buffercache des Kernels und den langsamen, aber großen Festplatten oder SSDs.
Je näher, desto schneller
Die klassische Speicherpyramide zeigt die Geschwindigkeitsunterschiede zwischen den Technologien (Abbildung 2). Bei DRAM sind die aus Kondensatoren bestehenden Speicherzellen zu einer Matrix angeordnet, die der Memorycontroller sehr schnell über ein Spalten- und Reihenprotokoll ansprechen kann. Der Controller sitzt architektonisch sehr nahe an der CPU und ist an sie über einen schnellen Parallelbus angebunden.
Die CPU dagegen spricht SSDs üblicherweise über Serial Attached SCSI (SAS) oder Serial-ATA (SATA) an. Diese Protokolle brauchen einen eigenen Host Bus Adapter, der üblicherweise via PCI-Express an die CPU angebunden ist. Selbst wer den Umweg über einen Extrachip vermeidet, etwa bei NVMe oder SCSI PQI, muss den Kernel die Daten immer noch in SCSI- oder NVMe-Pakete verpacken lassen, in den Hauptspeicher legen, dem DMA-Controller des Targets (die SSD oder NVMe-Karte) die Speicherregionen bekannt machen und den DMA-Transfer initiieren (zu den Fachbegriffen siehe Tabelle 1, [2]).
Damit nicht genug: Nach erfolgreicher Übertragung benachrichtigt ein Interrupt den Treiber, damit der die nächste Übertragung einleitet. Diese Übertragungen müssen zudem in der passenden Größe sein, denn eine Festplatte als Blockgerät verarbeitet bekanntlich Daten nur in einer vorgegebenen Paketgröße. Diese so genannte Sectorsize ist in der Regel 512 Bytes, bei große Festplatten und Flashspeicher-Medien 4096 Bytes.
Blockgeräte sind prinzipbedingt beim Verarbeiten von sehr vielen, sehr kleinen Dateneinheiten im Nachteil. Um diese Probleme in den Griff zu bekommen, antworten Betriebssysteme schon seit Langem mit Gegenstrategien: Die eine ist der Pagecache, der zwischen den Dateisystemen und dem Block-I/O-Layer des Kernels liegt und dafür sorgt, dass möglichst günstige Daten im Hauptspeicher lagern. Zum anderen versucht der I/O-Scheduler die Zugriffe auf die Hardware möglichst passend zu timen.
Tabelle 1
Glossar
|
Abkürzung |
Erklärung |
|---|---|
|
DRAM |
Dynamic Random Access Memory: Aus Kondensatoren aufgebauter, flüchtiger Speicher, typisch in PCs und Servern als Hauptspeicher eingesetzt. |
|
NV-DIMM |
Non-Volatile Direct Input Memory Modules: Sehr schneller DIMM-Speicher, wahlweise als Hauptspeicher oder als Massenspeicher verwendbar. |
|
DIMM |
Dual Inline Memory Module: zweireihige Speicherbausteine. |
|
DMA |
Direct Memory Access: Ein Methode, um Daten ohne Hilfe der CPU aus dem Hauptspeicher in Hardware zu übertragen. |
|
HBA |
Host Bus Adapter: Hardwareschnittstelle, die einen Computer mit einem Bus oder einem Netzwerksystem verbindet. Der Begriff ist vor allem in der SCSI-Welt gängig und bezeichnet dort die Adapter, die die Verbindung zu den Festplatten oder zum SAN herstellen. |
|
NVMe |
Non-Volatile Memory Express: Über PCI-Express, Infiniband oder Fibre Channel angebundener Flashspeicher, der gegenüber herkömmlichen SSDs geringere Latenzen und höheren Durchsatz erreicht. |
|
SCSI PQI |
SCSI PCIe Queueing Interface. |
Latenzarm und feingranular
Doch für einige Anwendungen reicht dies nicht. Hardware-Entwickler versuchen darum die Massenspeicher immer näher an die CPU zu bringen. Die populäre Aussage des Microsoft-Research-Mitarbeiters Jim Gray bringt es auf den Punkt: “Tape is Dead, Disk is Tape, Flash is Disk, RAM Locality is King” [3]. Während neuere Technologien immer mehr versucht haben die Speicher näher an den Memorycontroller zu bringen, ist es der neue Ansatz, den Massenspeicher parallel zum Hauptspeicher an den Memorycontroller zu platzieren.
Den Massenspeicher parallel zum Hauptspeicher zu haben bringt mehrere Vorteile: Zum einen verringert dies, wenig überraschend, die Latenz deutlich, also die Verzögerung zwischen Absetzen eines I/O-Request in Richtung Dateisystem und den ersten gelieferten Daten. Zum anderen wird die Blockgröße mehr oder weniger nebensächlich: Während Zugriffe auf die klassischen Blockgeräte eben nur in festen, recht großen Blöcken passieren, ist der Hauptspeicher Byte- oder Word-weise adressierbar. In der Praxis bestimmen aber auch die noch schnelleren CPU-Caches das Zugriffsverhalten auf den Hauptspeicher. Operationen, bei denen die Prozessorcaches praktische Auswirkung erlangen, weisen also eine Cacheline-Granularität auf.
Neue Möglichkeiten
Die Zugriffssemantiken von NV-DIMM und blockorientierten Geräten wie SSDs oder Festplatten unterscheiden sich enorm voneinander. Da NV-DIMMs wie Arbeitsspeicher angebunden sind, verhalten sie sich ähnlich, der Linux-Kernel spricht sie über eher RAM-orientierte Load/Store-Operationen an. Neu hinzugekommen sind Treiber, die daraus ultraschnelle Blockgeräte machen, die man über Read/Write-Operationen anspricht. Genau dies eröffnet sowohl dem Kernel als auch dafür angepassten Programmen neue Möglichkeiten.
Dateisysteme, die über das Direct-Access-Feature (DAX, [4]) verfügen – im Moment sind dies nur XFS und Ext 4 –, können die klassischen Request-Semantiken des Kernels für Blockgeräte umgehen und mit den NV-DIMM-Modulen direkt kommunizieren. Damit entfällt der Weg über den klassischen Hauptspeicher und die CPU braucht keine Gastspiele mehr für DMA-Completeion-IRQs zu veranstalten.
Nicht mit Raid
Einen Nachteil hat das Prozedere: Durch das direkte Ansprechen des Speichers aus den Dateisystemen fällt die Möglichkeit weg, Daten zu duplizieren, wie es etwa ein Software-Raid nötig macht. Wer seine Daten redundant ablegt, kann dieses Feature nicht nutzen, da die Software-Raid-Treiber nicht auf die Daten zugreifen können [5]. Das liegt daran, dass das Erzeugen und Speichern der Daten idealerweise auf den NV-DIMMs geschieht und dadurch auch das Kopieren vom DRAM in die NV-DIMMs wegfällt.
Wer gar den Kernel umgehen möchte, dem sei das NVML-Projekt [6] ans Herz gelegt. Es entwickelt eine Bibliothek für C und C++, die Spezifika von NV-DIMMs vor dem Programmierer verstecken soll und direkten Zugriff auf die Hardware ermöglicht. Dies eignet sich besonders für Backends von Datenbanken, die sowohl die Geschwindigkeit von In-Memory-Datenbanken benötigen als auch eine kurze Startzeit. Die Datensätze sind hier bereits vorhanden und müssen nicht erst in den Hauptspeicher kopiert werden. Eine Übersicht über die Software-Architektur der Linux-NV-DIMM-Unterstützung bietet Abbildung 3, mehr Details dazu weiß [7] zu berichten.
Integrität in der Arena
Wem die Integrität der Daten wichtiger ist als Geschwindigkeit, der sollte seine Aufmerksamkeit auf das NV-DIMM-BTT-Subsystem im Kernel richten. BTT steht für Block Translation Table und beschreibt die Methode, atomar auf NV-DIMMs zuzugreifen, wie man es von SCSI-Geräten gewohnt ist. Die Methode vollzieht Operationen entweder ganz oder gar nicht – eben atomar, unteilbar.
Liegt ein BTT auf dem NV-DIMM, teilt der Kernel den verfügbaren Speicherplatz in 512 GByte große Bereiche auf, so genannte Arenas. Den Anfang jeder Arena macht der 4 KByte große Arena Info Block. Das Ende bilden die BTT-Map und das BTT-Flog sowie eine 4 KByte große Kopie des Arena Info Block. Dazwischen finden sich die eigentlichen Daten.
Die BTT-Map ist eine simple Tabelle, die einen LBA auf die internen Blöcke des NV-DIMM übersetzt. Das BTT-Flog (ein Kunstwort bestehend aus Free List und Log) ist eine Liste, die die freien Blöcke auf dem NV-DIMM verwaltet. Jeder Schreibzugriff auf ein BTT-verwaltetes NV-DIMM geht zuerst auf einen freien Block aus dem Flog. Nur wenn dieser Schreibzugriff erfolgreich war, passt Linux die BTT-Map entsprechend an. Falls während des Schreibvorgangs ein Stromausfall eintritt, ist die alte Version der Daten noch so lange vorhanden, wie die BTT-Map noch nicht angepasst ist.
Listing 1
Dmesg zeigt den Speicher
01 # dmesg | grep BIOS-e820 02 [ 0.000000] e820: BIOS-provided physical RAM map: 03 [ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000005efff] usable 04 [ 0.000000] BIOS-e820: [mem 0x000000000005f000-0x000000000005ffff] reserved 05 [ 0.000000] BIOS-e820: [mem 0x0000000000060000-0x000000000009ffff] usable 06 [ 0.000000] BIOS-e820: [mem 0x00000000000a0000-0x00000000000fffff] reserved 07 [ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x0000000077470fff] usable 08 [ 0.000000] BIOS-e820: [mem 0x0000000077471000-0x00000000774f1fff] reserved 09 [ 0.000000] BIOS-e820: [mem 0x00000000774f2000-0x0000000078c82fff] usable 10 [ 0.000000] BIOS-e820: [mem 0x0000000078c83000-0x000000007ac32fff] reserved 11 [ 0.000000] BIOS-e820: [mem 0x000000007ac33000-0x000000007b662fff] ACPI NVS 12 [ 0.000000] BIOS-e820: [mem 0x000000007b663000-0x000000007b7d2fff] ACPI data 13 [ 0.000000] BIOS-e820: [mem 0x000000007b7d3000-0x000000007b7fffff] usable 14 [ 0.000000] BIOS-e820: [mem 0x000000007b800000-0x000000008fffffff] reserved 15 [ 0.000000] BIOS-e820: [mem 0x00000000fed1c000-0x00000000fed1ffff] reserved 16 [ 0.000000] BIOS-e820: [mem 0x0000000100000000-0x0000000c7fffffff] usable
Mit Linux testen
Das Ganze lässt sich heute schon mit einem Linux-System ab Kernel 4.1 testen, zu empfehlen sind jedoch Versionen ab der 4.6. Wer mag, kann selbst ohne passende Hardware mit Qemu NV-DIMM-Hardware emulieren. Abgesehen davon hält Linux die Möglichkeit bereit, auf der Kernel-Kommandozeile vom Bootmanager über den »memmap« -Parameter einen Teil des Hauptspeichers an das NV-DIMM-Subsystem abzutreten. Achtung: Ohne passende Hardware sind Schreiboperationen auf diesen Bereich logischerweise nicht persistent.
Der Aufruf »memmap=16G!4G« reserviert 16 GByte RAM beginnend ab 4 GByte und übergibt sie dem NV-DIMM-Treiber. Freie Bereiche zeigt Dmesg an (Listing 1). Bereiche, die hier als »usable« gekennzeichnet sind, kann der NV-DIMM-Treiber benutzen. Ist die Kernel-Kommandozeile angepasst und das System neu gestartet, findet sich ein Eintrag wie in Listing 2 im Kernel-Log. Der Speicher ist erkennbar geteilt: »0x0000000100000000« bis »0x00000004ffffffff« hat der Kernel als »persistent (type 12)« markiert. Hier wird sich nach dem Laden der Treiber das »/dev/pmem0« -Gerät manifestieren. Nun kann Root mit
mkfs.xfs /dev/pmem0
ein XFS-Dateisystem anlegen und es wie gewohnt mit
mount -o dax /dev/pmem0 /mnt
einhängen. Zu beachten ist hierbei die Mount-Option »dax« , welche die bereits erwähnte DAX-Funktionalität aktiviert.
Listing 2
Dmesg mit aktiver NV-DIMM-Memmap
01 [ 0.000000] user: [mem 0x0000000000000000-0x000000000005efff] usable 02 [ 0.000000] user: [mem 0x000000000005f000-0x000000000005ffff] reserved 03 [ 0.000000] user: [mem 0x0000000000060000-0x000000000009ffff] usable 04 [ 0.000000] user: [mem 0x00000000000a0000-0x00000000000fffff] reserved 05 [ 0.000000] user: [mem 0x0000000000100000-0x0000000075007017] usable 06 [ 0.000000] user: [mem 0x0000000075007018-0x000000007500f057] usable 07 [ 0.000000] user: [mem 0x000000007500f058-0x0000000075010017] usable 08 [ 0.000000] user: [mem 0x0000000075010018-0x0000000075026057] usable 09 [ 0.000000] user: [mem 0x0000000075026058-0x0000000077470fff] usable 10 [ 0.000000] user: [mem 0x0000000077471000-0x00000000774f1fff] reserved 11 [ 0.000000] user: [mem 0x00000000774f2000-0x0000000078c82fff] usable 12 [ 0.000000] user: [mem 0x0000000078c83000-0x000000007ac32fff] reserved 13 [ 0.000000] user: [mem 0x000000007ac33000-0x000000007b662fff] ACPI NVS 14 [ 0.000000] user: [mem 0x000000007b663000-0x000000007b7d2fff] ACPI data 15 [ 0.000000] user: [mem 0x000000007b7d3000-0x000000007b7fffff] usable 16 [ 0.000000] user: [mem 0x000000007b800000-0x000000008fffffff] reserved 17 [ 0.000000] user: [mem 0x00000000fed1c000-0x00000000fed1ffff] reserved 18 [ 0.000000] user: [mem 0x0000000100000000-0x00000004ffffffff] persistent (type 12) 19 [ 0.000000] user: [mem 0x0000000500000000-0x0000000c7fffffff] usable
Speed-Test
Wer schon NV-DIMMs besitzt und sich des Geschwindigkeitsvorteils versichern will, dem reicht ein kurzer Test mit dem Unix-Tool DD. In Listing 3 kopiert Root 4 GByte vom Null-Gerät »/dev/zero« auf den Pmem-Mountpoint. Das Flag »oflag=direct« hilft, den Puffer-Cache des Kernels zu umgehen, und ruft so die Power echter NV-DIMMs (aus der Vorserie von HP) ab. Der gleiche Test auf der Festplatte des Host liefert Werte um die 50 MByte/s (über 80 Sekunden Laufzeit).
Listing 3
Benchmark
01 $ dd if=/dev/zero of=/mnt/test.dat oflag=direct bs=4k count=$((1024*1024)) 02 1048576+0 records in 03 1048576+0 records out 04 4294967296 bytes (4.3 GB, 4.0 GiB) copied, 4.55899 s, 942 MB/s
Verfügbarkeit
Für jedermann frei käuflich werden NV-DIMMs wohl ab 2017 sein. Um den Linux-Kernel schnell fit für die schnellen Riegel zu machen, stellt die Industrie engagierten Kernelentwicklern wie den Suse Labs Muster bereit. Von den Ergebnissen profitieren alle Distributionen (Upstream). Der Einbau der passenden Kernel und Treiber erfolgt dann sukzessive. Schon heute beherrschen vier Distributionen den Umgang mit NV-DIMMs:
- Open Suse Tumbleweed
- Open Suse Leap 42.2
- Suse Linux Enterprise 12 SP 2
- Fedora 24
Zu Debian und Ubuntu ergab die Recherche der Autoren keine Anhaltspunkte; höchstwahrscheinlich werden diese bis nächstes Jahr nachziehen.
Infos
- Jedec JC-45: http://www.jedec.org/committees/jc-456-0
- DRAM: https://de.wikipedia.org/wiki/Dynamic_Random_Access_Memory
- “DDR4 NVDIMM Standardization”: http://www.jedec.org/sites/default/files/files/Brett_Williams_Server_Forum_2014.pdf
- Jonathan Corbet, “Supporting filesystems in persistent memory”: http://lwn.net/Articles/610174/
- Neil Brown, “DAX and fsync: the cost of forgoing page structures”: http://lwn.net/Articles/676737/
- NVML NV-DIMM Library: https://github.com/pmem/nvml/
- NV-DIMM Software Architecture: http://pmem.io/2014/08/27/crawl-walk-run.html











