io_uring ohne Readahead: Warum Turso 4,8 Millionen Cache-Misses mehr kassiert
Io_uring Without Readahead
Ein PR für Turso implementiert Readahead für den io_uring-Backend. Die Messungen zeigen: Mit Readahead sinkt die Zahl der Geräte-Requests von ~196.000 auf ~16.300, weil der Block-Layer benachbarte Requests zusammenführt. Ohne Readahead leidet io_uring unter fehlender Parallelität – nur ein SQE ist gleichzeitig in der Warteschlange. Der Autor analysiert zudem die Kosten von SQ-Polling (65% der CPU-Zyklen im Polling-Thread) und zeigt, dass O_DIRECT die CPU-Caches umgeht, was zu mehr Cache-Misses führt. Ein Vergleich mit dem syscall-Backend: 8,55s vs. 3,02s für Q6.
Mit O_DIRECT schreibt die Disk die Daten direkt in den Prozesspuffer, ohne den Kopierschritt – das bedeutet, die CPU wird nicht in den Prozess einbezogen, also wird nichts in die CPU-Caches kopiert.
- ComputerGuru
Interessanter Artikel, aber er hat mir einen kleinen Panikanfall beschert. Benchmarking (mit TPC oder anderem) ist NICHT der richtige Weg, um hier den korrekten Ansatz zu bestimmen; das ist streng genommen nur für Datenbanken (typischerweise RDBMS) gedacht, die die gesamte Hardware, auf der sie laufen, effektiv "besitzen". Eine eingebettete Datenbank könnte auf diese Weise verwendet werden, wenn sie als Backend für eine reine CRUD-Anwendung dient, die so gut wie kein serverseitiges Rendering, Parsen, Validieren usw. durchführt und im Wesentlichen nur eine asynchrone HTTP-zu-SQLite-Schnittstelle ist. Aber eher wahrscheinlich wird eine eingebettete DB auf Maschinen (nicht unbedingt Servern) verwendet und bereitgestellt, die vielen Zwecken dienen, und sie muss sowohl innerhalb der Grenzen der verfügbaren Ressourcen der Maschine als auch in relativer Hinsicht am besten abschneiden, wobei notwendigerweise Kompromisse eingegangen werden, die Leistung für "Wert" in Bezug auf CPU- oder Speichernutzung opfern könnten.
Dies gilt nicht nur im Hinblick auf Benchmarking, sondern ist eine wesentliche Überlegung, *jedes Mal*, wenn Sie die Kontrolle über den Cache vom Kernel übernehmen, der das einzige Stück im Stack ist, das Einblick in den globalen Zustand hat und dem man vertrauen kann, dass er Speicher unter Druck zurückgibt, um sicherzustellen, dass alles gut zusammenspielt. Es beschränkt sich nicht nur auf Datenbanken oder sogar nur auf Speicher; zum Beispiel hatte FreeBSD mehr als genug Probleme, die auf ZFS mit einem separaten Cache vom Kernel zurückzuführen sind (trotz der engeren Integration zwischen den beiden und des Vorhandenseins verschiedener Mechanismen zur Bewältigung pathologischer [...]
- marginalia_nu
Wenn Sie zusammenhängendes Read-Ahead im Userspace durchführen, warum dann nicht einfach preadv verwenden? Das beschränkt Sie darauf, Read-Ahead bis zur nächsten residenten Seite zu betreiben, aber zumindest in meinen Experimenten mit Marginalias Index schlägt preadv io_uring in allen Fällen, in denen Sie einen einzigen preadv-Aufruf verwenden können, um das vollständige Lesen durchzuführen.
- amluto
Ich bin neugierig, warum die Wahl zwischen Syscalls und speziell io_uring mit O_DIRECT getroffen wird. Soweit ich weiß, ist Turso wie SQLite und unterstützt mehrere Prozesse, die auf dieselbe Datenbank zugreifen, und ich würde erwarten, dass Pufferung bei einigen Workloads ein großer Gewinn ist. Was ist falsch an io_uring ohne Direct? Es gibt auch den Mittelweg von RWF_DONTCACHE.
- ErroneousBosh
Das ist in meinem Feed vorbeigescrollt und jedes Mal habe ich es als "Io_uring ohne Radiohead" gelesen, und ich meine, man könnte es tun, aber was wäre der Sinn?
- weatherlite
Verwendet Io_urine gelbe Fäden?