- Untersuchung der Implementierung von Unix-Pipes unter Linux und von Methoden zur Optimierung von Testprogrammen, die Daten über Pipes schreiben und lesen
- Das ursprüngliche Programm erreichte einen Durchsatz von etwa 3,5 GiB/s, der durch verschiedene Optimierungen um das 20-Fache gesteigert wurde
- Diese Optimierungen wurden durch Profiling des Programms mit dem Linux-Tool
perf erzielt
- Der Artikel ist inspiriert von einem optimierten FizzBuzz-Programm, das Ausgaben mit etwa 35 GiB/s in eine Pipe schiebt
- Es wird tiefgehend untersucht, wie Pipes intern funktionieren, warum Schreiben in und Lesen aus ihnen langsam ist und wie die Systemaufrufe
vmsplice und splice die Leistung verbessern können
- Es wird erläutert, wie Linux-Paging und der Einsatz von Huge Pages zu schnelleren Versionen des Programms führen können
- Die abschließende Optimierung besteht darin, Polling durch eine Busy Loop zu ersetzen
- Die Tests wurden auf einer Intel-Skylake-i7-8550U-CPU und unter Linux 5.17 durchgeführt
- Der Artikel erklärt im Detail, wie Speicher aus Seiten fester Größe aufgebaut ist und wie die CPU Seitentabellen verwendet, um virtuelle Adressen in physische Adressen zu übersetzen
- Der Artikel kommt zu der Beobachtung, dass der Wechsel auf Huge Pages in dem Programm die Leistung um etwa 50 % verbessert
- Es wird außerdem der Einsatz von Huge Pages auf der CPU und die Verringerung von Translation Lookaside Buffer (TLB)-Misses behandelt, was die Leistung verbessern kann
- Der Kernel-Code geht davon aus, dass
struct page auf eine Seite der Standardgröße der aktuellen Architektur verweist. Bei Huge Pages enthält die "head"-struct page Informationen über die tatsächliche physische Seite, während die fortlaufenden "tail"-Seiten nur einen Zeiger auf die Head-Seite enthalten
- Neuere Kernel (seit 5.17) enthalten mit
struct folio einen neuen Typ, der Head-Seiten explizit identifiziert. Dadurch muss zur Laufzeit seltener geprüft werden, ob eine struct page eine Head- oder Tail-Seite ist, was die Leistung verbessert
- Der Artikel behandelt das Konzept der Busy Loop zur Vermeidung von Synchronisierungskosten. Dabei wird
vmsplice angewiesen, zurückzukehren, wenn nicht in die Pipe geschrieben werden kann, und dann in einer Busy Loop zu laufen, bis es wieder bereit ist. Das kann eine Leistungssteigerung von 25 % bringen, hat aber den Preis, einen CPU-Kern vollständig zu belegen, bis vmsplice wieder bereit ist
- Der Autor fasst die im Artikel behandelten Hauptthemen zusammen: Zero-Copy-Operationen, Ringpuffer, Paging & virtueller Speicher, Synchronisierungs-Overhead
- Der Autor räumt außerdem ein, dass es viele weitere Optionen und Details gibt, die im Artikel nicht behandelt werden, entweder weil sie nicht relevant sind oder weil das Interesse daran fehlte
- Der Artikel wurde von den Lesern gut aufgenommen, weil sie ihn als hilfreich und interessant empfanden
1 Kommentare
Hacker-News-Kommentare
vmsplice, das als eine Art Mini-Shared-Memory-Mechanismus zwischen zwei Prozessen funktioniertvmspliceerfordert beim Lesen und Schreiben eine sorgfältige Behandlung der Puffer und ist komplex, kann aber effizient seinsplice()undvmsplice(), die in den meisten Programmen schwer zu verwenden sind und laut Bericht kaum genutzt werdenstdouteines Programms auf denstdineines anderen, wodurch der Vorgang alszerocopyoder in weniger optimierten Fällen als schnellesonecopyerfolgtperfund betont deren Bedeutung für den Durchsatzcat,sed,awk,cut,grep,uniqundjqwiederholt auszuführen und zu kombinieren