Wann sollte ich /dev/shm/ und wann sollte ich /tmp/ verwenden?
Wann sollte ich /dev/shm/
und wann sollte ich /tmp/
verwenden? Kann ich mich bei Unices immer darauf verlassen, dass beide vorhanden sind?
Wann sollte ich /dev/shm/
und wann sollte ich /tmp/
verwenden? Kann ich mich bei Unices immer darauf verlassen, dass beide vorhanden sind?
In absteigender Reihenfolge der tmpfs
Wahrscheinlichkeit:
┌───────────┬──────────────┬────────────────┐
│ /dev/shm │ always tmpfs │ Linux specific │
├───────────┼──────────────┼────────────────┤
│ /tmp │ can be tmpfs │ FHS 1.0 │
├───────────┼──────────────┼────────────────┤
│ /var/tmp │ never tmpfs │ FHS 1.0 │
└───────────┴──────────────┴────────────────┘
Da Sie nach einem Linux-spezifischen tmpfs-Mountpoint im Gegensatz zu einem portabel definierten Verzeichnis fragen, das tmpfs sein kann (abhängig von Ihrem Systemadministrator und den Standardeinstellungen Ihrer Distribution), hat Ihre Frage zwei Aspekte, die andere Antworten unterschiedlich betont haben:
Konservative Ausgabe (Mischung aus Konventionen aus FHS und allgemeinem Gebrauch):
/tmp
verwenden. /var/tmp
für große Daten, die nicht ohne weiteres in den Ram passen. /var/tmp
für Daten, die auch nach einem Neustart erhalten bleiben sollen (z. B. ein Cache). /dev/shm
als Nebeneffekt des Aufrufs von shm_open()
. Das Zielpublikum sind begrenzte Puffer, die endlos überschrieben werden. Dies ist also für langlebige Dateien, deren Inhalt flüchtig und nicht furchtbar groß ist. mktemp
die Umgebungsvariable TMPDIR
. Pragmatische Ausgabe:
Verwenden Sie /dev/shm
, wenn es wichtig ist, tmpfs zu verwenden, /var/tmp
, wenn es wichtig ist, es nicht zu verwenden, ansonsten /tmp
.
fsync
ist ein No-op auf tmpfs. Dieser Syscall ist der größte Feind der (IO-)Leistung (und der Langlebigkeit des Flashs, wenn Sie sich dafür interessieren). Wenn Sie sich dabei ertappen, dass Sie tmpfs (oder eatmydata ) nur benutzen, um fsync zu umgehen, dann machen Sie (oder ein anderer Entwickler in der Kette) etwas falsch. Es bedeutet, dass die Transaktionen in Richtung des Speichergeräts für Ihren Zweck unnötig feinkörnig sind - Sie sind offensichtlich bereit, einige Savepoints für die Leistung zu überspringen, da Sie jetzt zum Extrem gegangen sind, sie alle zu sabotieren - selten der beste Kompromiss. Außerdem ist es hier im Land der Transaktionsleistung, wo einige der größten Vorteile einer SSD liegen - jede anständige SSD wird im Vergleich zu dem, was eine rotierende Festplatte aushalten kann (7200 U/min = 120 Hz, wenn nichts anderes darauf zugreift), eine überragende Leistung erbringen, ganz zu schweigen von Flash-Speicherkarten, die sich in dieser Metrik stark unterscheiden (nicht zuletzt, weil es ein Kompromiss mit der sequenziellen Leistung ist, nach der sie bewertet werden, z. B. SD-Karten-Klasseneinstufung). Seien Sie also vorsichtig, Entwickler mit rasend schnellen SSDs, und zwingen Sie Ihre Benutzer nicht in diesen Anwendungsfall!
Wollen Sie eine lächerliche Geschichte hören? Meine erste fsync
Lektion: Ich hatte einen Job, bei dem es darum ging, routinemäßig eine Reihe von Sqlite-Datenbanken (die als Testfälle aufbewahrt wurden) auf ein sich ständig änderndes aktuelles Format zu “aktualisieren”. Das “Upgrade”-Framework ließ eine Reihe von Skripten laufen, die jeweils mindestens eine Transaktion ausführten, um eine Datenbank zu aktualisieren. Natürlich aktualisierte ich meine Datenbanken parallel (8 parallel, da ich mit einer mächtigen 8-Kern-CPU gesegnet war). Aber wie ich herausfand, gab es überhaupt keinen Geschwindigkeitszuwachs bei der Parallelisierung (eher einen leichten Schlag), da der Prozess vollständig IO-gebunden war. Lustigerweise war das Upgrade-Framework in ein Skript verpackt, das jede Datenbank nach /dev/shm
kopierte, sie dort aktualisierte und zurück auf die Festplatte kopierte, etwa 100 Mal schneller (immer noch mit 8 parallel). Als Bonus war der PC auch benutzbar, während die Datenbanken aktualisiert wurden.
Die angemessene Verwendung von tmpfs ist, unnötiges Schreiben von flüchtigen Daten zu vermeiden. Effektives Deaktivieren von writeback, wie das Setzen von /proc/sys/vm/dirty_writeback_centisecs
auf unendlich auf einem normalen Dateisystem.
Das hat sehr wenig mit der Leistung zu tun, und ein Versagen ist ein viel kleineres Problem als der Missbrauch von fsync: Der Writeback-Timeout bestimmt, wie träge der Festplatteninhalt nach dem Pagecache-Inhalt aktualisiert wird, und die Vorgabe von 5 Sekunden ist eine lange Zeit für einen Computer - eine Anwendung kann eine Datei im Pagecache so oft überschreiben, wie sie will, aber der Inhalt auf der Festplatte wird nur etwa einmal alle 5 Sekunden aktualisiert. Es sei denn, die Anwendung erzwingt dies mit fsync. Überlegen Sie, wie oft eine Anwendung eine kleine Datei in dieser Zeit ausgeben kann, und Sie sehen, warum es ein viel größeres Problem wäre, jede einzelne Datei mit fsync zu erzwingen.
fsync
. Aufbewahrung von kalten Daten. Man könnte versucht sein zu denken, dass das Auslagern von Dateien aus dem Swap genauso effizient ist wie ein normales Dateisystem, aber es gibt ein paar Gründe, warum das nicht so ist:
Der einfachste Grund: Es gibt nichts, was moderne Speichergeräte (egal ob Festplatten- oder Flash-basiert) mehr lieben, als ziemlich sequentielle Dateien zu lesen, die durch ein ordentliches Dateisystem ordentlich organisiert sind. Das Austauschen von 4KiB-Blöcken wird das wahrscheinlich nicht verbessern.
Die versteckten Kosten: Auslagern aus. Tmpfs-Seiten sind schmutzig - sie müssen irgendwo hingeschrieben werden (in den Swap), um aus dem Pagecache entfernt zu werden, im Gegensatz zu dateibasierten reinen Seiten, die sofort gelöscht werden können. Das ist eine zusätzliche Schreibstrafe für alles andere, was um Speicher konkurriert - betrifft etwas anderes zu einem anderen Zeitpunkt als die Verwendung dieser tmpfs-Seiten.
Okay, hier ist die Realität.
Sowohl tmpfs als auch ein normales Dateisystem sind ein Speicher-Cache über die Festplatte.
Das tmpfs verwendet Speicher und Swapspace als Backup-Speicher, ein Dateisystem verwendet einen bestimmten Bereich auf der Festplatte, keines von beiden ist in der Größe des Dateisystems begrenzt, es ist durchaus möglich, ein 200 GB großes tmpfs auf einer Maschine mit weniger als einem GB Ram zu haben, wenn Sie genug Swapspace haben.
Der Unterschied liegt darin, wann die Daten auf die Platte geschrieben werden. Bei einem tmpfs werden die Daten NUR geschrieben, wenn der Speicher zu voll wird oder die Daten wahrscheinlich nicht bald gebraucht werden. OTOH die meisten normalen Linux-Dateisysteme sind so konzipiert, dass sie immer einen mehr oder weniger konsistenten Datensatz auf der Platte haben, so dass, wenn der Benutzer den Stecker zieht, nicht alles verloren geht.
Ich persönlich bin es gewohnt, Betriebssysteme zu haben, die nicht abstürzen, und USV-Systeme (z.B.: Laptop-Akkus), daher denke ich, dass die ext2/3-Dateisysteme mit ihrem 5-10-Sekunden-Checkpoint-Intervall zu paranoid sind. Das ext4-Dateisystem ist mit einem 10-Minuten-Checkpoint besser, nur behandelt es die Benutzerdaten als zweitklassig und schützt sie nicht. (ext3 ist das gleiche, aber man merkt es nicht wegen des 5-Sekunden-Checkpoints)
Dieses häufige Checkpointing bedeutet, dass ständig unnötige Daten auf die Platte geschrieben werden, sogar für /tmp.
Das Ergebnis ist also, dass Sie einen Swap-Speicherplatz anlegen müssen, der so groß ist, wie Ihr /tmp sein muss (selbst wenn Sie eine Auslagerungsdatei anlegen müssen) und diesen Platz nutzen, um ein tmpfs der benötigten Größe auf /tmp zu mounten.
Verwenden Sie NIEMALS /dev/shm.
Es sei denn, Sie verwenden es für sehr kleine (wahrscheinlich mmap’d) IPC-Dateien und Sie sind sicher, dass es existiert (es ist kein Standard) und der Rechner hat mehr als genug Speicher + Swap zur Verfügung.
Verwenden Sie /tmp/ für temporäre Dateien. Verwenden Sie /dev/shm/, wenn Sie gemeinsamen Speicher benötigen (d. h. für die Kommunikation zwischen Prozessen über Dateien).
Sie können sich darauf verlassen, dass /tmp/ vorhanden ist, aber /dev/shm/ ist eine relativ neue Sache nur für Linux.
Ein weiterer Fall, in dem Sie /dev/shm (für Linux 2.6 und höher) verwenden sollten, ist, wenn Sie ein garantiertes tmpfs-Dateisystem benötigen, weil Sie nicht wissen, ob Sie auf die Festplatte schreiben können.
Ein Überwachungssystem, mit dem ich vertraut bin, muss temporäre Dateien schreiben, während es seinen Bericht zur Übermittlung an einen zentralen Server erstellt. In der Praxis ist es weitaus wahrscheinlicher, dass etwas das Schreiben auf ein Dateisystem verhindert (entweder ist kein Speicherplatz mehr vorhanden oder ein zugrundeliegender RAID-Fehler hat das System in einen Hardware-Schreibschutz-Modus versetzt), Sie aber immer noch in der Lage sind, weiter zu humpeln, um darüber zu alarmieren, als wenn etwas den gesamten verfügbaren Speicher derart verschlingt, dass tmpfs unbrauchbar wird (und der Rechner nicht tot ist). In solchen Fällen wird ein Überwachungssystem es vorziehen, in den Arbeitsspeicher zu schreiben, um möglicherweise eine Warnung über eine volle Festplatte oder tote/sterbende Hardware senden zu können.
/dev/shm wird für systemeigene Gerätetreiber und Programme im gemeinsamen virtuellen Speicher verwendet.
Wenn Sie ein Programm erstellen, das einen virtuellen Speicherheap benötigt, sollte dieser im virtuellen Speicher abgebildet werden. Dies gilt doppelt, wenn Sie mehrere Prozesse oder Threads benötigen, die sicher auf diesen Speicher zugreifen können.
Nur weil der Treiber eine spezielle Version von tmpfs dafür verwendet, heißt das nicht, dass Sie es als generische tmpfs-Partition verwenden sollten. Stattdessen sollten Sie einfach eine weitere tmpfs-Partition anlegen, wenn Sie eine für Ihr temporäres Verzeichnis benötigen.
In PERL, mit 8GB Minimum auf jeder Maschine (alle unter Linux Mint), bin ich von dem, was ich denke, ist eine gute Gewohnheit, DB_File-basierte (Datenstruktur in einer Datei) komplexe Algorithmen mit Millionen von Lese- und Schreibvorgängen mit /dev/shm
In anderen Sprachen, nicht mit gigether überall, um die Starts und Stopps bei der Netzwerkübertragung zu vermeiden (wenn ich lokal an einer Datei arbeite, die in einer Client-Server-Atmosphäre auf einem Server liegt), kopiere ich mit einer Art Batch-Datei die gesamte (300-900MB) Datei auf einmal nach /dev/shm, führe das Programm mit der Ausgabe auf /dev/shm aus, schreibe die Ergebnisse zurück auf den Server und lösche von /dev/shm
Wenn ich weniger RAM hätte, würde ich das natürlich nicht tun. Normalerweise ist das In-Memory-Dateisystem von /dev/shm so groß wie die Hälfte des verfügbaren RAMs. Der normale Gebrauch von RAM ist jedoch konstant. Sie könnten dies also wirklich nicht auf einem Gerät mit 2 GB oder weniger tun. Um es überspitzt auszudrücken: Es gibt oft Dinge im RAM, die selbst das System nicht richtig meldet.