Eine Forschergruppe aus deutschen Universitäten die Ergebnisse , bei dem in verschiedenen Programmiersprachen zehn Varianten eines Standardtreibers für Intel Ixgbe (X5xx) 10-Gigabit-Netzwerkkarten entwickelt wurden. Der Treiber läuft im Benutzermodus und ist in den Sprachen C, Rust, Go, C#, Java, OCaml, Haskell, Swift, JavaScript und Python implementiert. Beim Schreiben des Codes wurde besonderes Augenmerk auf die Maximierung der Leistung unter Berücksichtigung der Besonderheiten jeder Sprache gelegt. Funktional sind alle Varianten identisch und bestehen aus etwa 1000 Zeilen Code. Die Ergebnisse des Projekts unter der BSD-Lizenz.
Die Treibervariante in Rust erwies sich in Bezug auf die Leistung als sehr nah am Referenztreiber in C. Bei einer Belastung mit gleichzeitiger Sendung von Blöcken zu jeweils 32 Paketen lag der Rust-Treiber etwas zurück, zeigte jedoch bei Tests mit mehr als 32 Paketen im Block praktisch keinen Geschwindigkeitsunterschied zum Treiber in C und erreichte eine Leistung von 28 Millionen Paketen pro Sekunde auf einem Server mit einem Xeon E3-1230 v2 3,3 GHz CPU.
Die nächste Leistungsstufe wurde von den Treibern in den Sprachen Go und C# eingenommen, die ziemlich ähnliche Ergebnisse erzielten (der Go-Treiber war in Tests mit Blöcken bis zu 16 Paketen überlegen, jedoch etwas im Nachteil bei Tests mit mehr als 16 Paketen pro Block). Bei 256 Paketen pro Block erreichte der C#-Treiber eine Spitzenleistung von etwa 28 Millionen Paketen pro Sekunde, während der Go-Treiber etwa 25 Millionen Pakete pro Sekunde erzielte.
Anschließend folgten mit ziemlich ähnlichen Ergebnissen die Treiber in
Java, OCaml und Haskell, die bereits deutlich hinter den vorher betrachteten Alternativen zurückblieben und die Marke von 12 Millionen Paketen pro Sekunde nicht übertreffen konnten. Noch größer war der Rückstand bei den Treibern für Swift und JavaScript, die nur Streams auf einem Niveau von 5 Millionen Paketen pro Sekunde verarbeiten konnten.
Der Python-Treiber erreichte nur 0,14 Millionen Pakete pro Sekunde. Die Implementierung in Python wurde verwendet, um die Geschwindigkeit von Interpretern ohne JIT und spezifische Optimierungen zu bewerten (der Code wurde mit CPython 3.7 ausgeführt und war nicht mit PyPy kompatibel, aber es wird angemerkt, dass die Optimierung der Datenstrukturen die Leistung um etwa das Zehnfache steigern könnte).
Zusätzlich wurden Tests zur Latenzzeit durchgeführt, die die Effizienz der Pufferung und den Einfluss des Garbage Collectors zeigten. Bei den Tests wurde die Latenz nach der Weiterleitung jedes Pakets durch den Treiber im Vergleich zur genau bekannten Versandzeit gemessen. Die Führer blieben weiterhin die Treiber in C und Rust, deren Ergebnisse für einen Durchsatz von 1 Million Paketen pro Sekunde praktisch nicht zu unterscheiden waren (ungefähr 20 µs). Der Treiber in Go schnitt ebenfalls gut ab und lag nur minimal hinter den Spitzenreitern, ebenfalls auf 20 µs. Der Treiber in C# wies Latenzen von etwa 50 µs auf.
Die höchsten Latenzen wurden von den Treibern in JavaScript und Java gemeldet (Latenzen über 300 µs).
Die Untersuchung wurde durchgeführt, um die Möglichkeiten zur Entwicklung von Treibern und Betriebssystemkomponenten in höheren Programmiersprachen als C zu bewerten. Derzeit entfallen 39 von 40 Speicherproblemen in Linux auf Treiber, weshalb die Fragen zur Anwendung einer sichereren Sprache und zur Auslagerung von Treibern aus dem Kernel in den Benutzermodus weiterhin von Bedeutung sind. Die Hersteller experimentieren bereits aktiv in diese Richtung (zum Beispiel hat Google einen TCP-Stack für das Betriebssystem in der Programmiersprache Go entwickelt, das Unternehmen CloudFlare eine Implementierung des QUIC-Protokolls in Rust geschaffen, und Apple hat den TCP-Stack auf mobilen Geräten in den Benutzermodus verschoben).
Die durchgeführte Arbeit zeigt, dass die Programmiersprache Rust der beste Kandidat für die Entwicklung von Treibern ist. Die in Rust bereitgestellten Möglichkeiten ermöglichen es, Probleme, die durch die niedriglevelige Speicherverwaltung entstehen, zu umgehen, wobei die Leistung um etwa 2 % bis 10 % im Vergleich zu Treibern in C verringert wird. Auch die Sprachen Go und C# wurden als geeignet für die Erstellung von Systemkomponenten anerkannt, in Situationen, in denen Millisekunden-Verzögerungen durch die Verwendung eines Garbage Collectors akzeptabel sind.
Quelle: opennet.ru
