11 Punkte von opal58 2023-01-07 | 4 Kommentare | Auf WhatsApp teilen

Ich möchte einen interessanten Artikel vorstellen, den ich anderswo gelesen habe.

Rust und C++ werden in vielerlei Hinsicht oft miteinander verglichen. Einen direkten Vergleich der Kompilierzeiten anzustellen, war jedoch schwierig, weil es selten vorkommt, dass dasselbe Projekt in beiden Sprachen geschrieben ist. Bei quick-lint-js wurde ein in C++ geschriebenes Projekt teilweise in Rust neu umgesetzt, um die Kompilierzeiten zu vergleichen. Allerdings wurde Windows aus der Build-Umgebung ausgeschlossen.

Kriterien für das Portieren

  • Bibliotheken von Drittanbietern ausgeschlossen
  • Arbeit unter Linux und macOS
  • Umfangreiche Test-Suite
  • FFI, Pointer, Standard- und selbst geschriebene Container, Utility-Klassen und -Funktionen, I/O, Nebenläufigkeit, Generics, Makros, SIMD, Vererbung, ...

Fazit

  • Die Kompilierzeit von Rust ist ähnlich wie bei C++ oder langsamer (zumindest in diesem Projekt)
  • In Rust muss mehr Code geschrieben werden als in C++
  • Bei vollständigen (Full) Builds ist C++ ähnlich schnell oder schneller
  • Bei inkrementellen (Incremental) Builds ist die Build-Zeit manchmal kürzer und manchmal länger (in manchen Fällen sogar deutlich länger)
  • Es wurde entschieden, den Rest von quick-lint-js nicht nach Rust zu portieren (vielleicht doch, falls sich die Build-Zeit verbessern lässt?)

4 Kommentare

 
freedomzero 2023-01-11

Auch hierzulande gibt es offenbar viele Menschen, die Rust verwenden. Mich würde interessieren, in welchen Branchen ihr alle arbeitet.

 
cr543l 2023-01-07

Mich würde interessieren, wie es bei Rust ist: Nach dem ersten Kompilieren geht es bei C++ ja sehr schnell, wenn man einzelne .cpp-Dateien statt stark abhängiger Header-Dateien ändert.

 
ssssss 2023-01-07

In der Rubrik mit den häufig gestellten Fragen der Rust-Dokumentation wird das recht ausführlich erklärt, daher teile ich es hier einmal.

====================================
Rust-Kompilierung scheint langsam zu sein. Warum ist das so?

Weil der Code in Maschinensprache übersetzt und dabei optimiert wird. Rust bietet High-Level-Abstraktionen, die zu effizientem Maschinencode kompiliert werden, und dieser Übersetzungsprozess braucht naturgemäß Zeit, besonders wenn optimiert wird.

Allerdings sind die Compile-Zeiten von Rust nicht so schlecht, wie man vielleicht denkt, und es gibt gute Gründe anzunehmen, dass sie sich künftig weiter verbessern werden. Vergleicht man ähnlich große Projekte in C++ und Rust, ist die Zeit für die Kompilierung des Gesamtprojekts im Allgemeinen vergleichbar. Der Hauptgrund, warum sich Rust-Kompilierung langsam anfühlt, liegt im unterschiedlichen Kompilierungsmodell von C++ und Rust: Bei C++ ist die Kompilierungseinheit eine einzelne Datei, bei Rust dagegen ein Crate aus mehreren Dateien. Wenn man also während der Entwicklung eine einzelne C++-Datei ändert, kann die Compile-Zeit im Vergleich zu Rust deutlich geringer ausfallen. Derzeit läuft eine größere Umstrukturierung des Rust-Compilers, um inkrementelle Kompilierung zu ermöglichen; wenn sie abgeschlossen ist, dürften sich die Compile-Zeiten in Rust ähnlich wie im C++-Modell verbessern.

Unabhängig vom Kompilierungsmodell gibt es in Rusts Sprachdesign mehrere Faktoren, die sich auf die Compile-Zeit auswirken.

Erstens hat Rust ein vergleichsweise komplexes Typsystem, und es muss eine nicht zu vernachlässigende Menge an Compile-Zeit darauf verwenden, die Einschränkungen durchzusetzen, die Rust zur Laufzeit sicher machen.

Zweitens gibt es im Rust-Compiler technische Altlasten, insbesondere ist die Qualität des erzeugten LLVM IR nicht besonders gut, sodass LLVM Zeit darauf verwenden muss, es zu „reparieren“. Künftig könnten MIR-basierte Optimierungs- und Übersetzungsschritte die Last verringern, die der Rust-Compiler LLVM aufbürdet.

Drittens ist die Nutzung von LLVM für die Codegenerierung in Rust ein zweischneidiges Schwert. Dank LLVM erreicht Rust Laufzeitleistung auf Weltklasseniveau, aber LLVM ist ein riesiges Framework, das nicht auf Compile-Zeit optimiert ist und besonders anfällig für Eingaben von niedriger Qualität ist.

Schließlich erzeugt Rust mit seiner Strategie, generische Typen ähnlich wie C++ zu monomorphisieren, zwar schnellen Code, hat aber den Nachteil, im Vergleich zu anderen Übersetzungsstrategien erheblich mehr Code erzeugen zu müssen. Dieser Code-Bloat lässt sich durch den Einsatz von Trait-Objekten gegen dynamischen Dispatch mit seinen jeweiligen Vor- und Nachteilen eintauschen.

 
bus710 2023-01-07

Sicher ist jedenfalls, dass Rust-Projekte beim Build enorm viel Festplattenspeicher fressen. Ich erinnere mich noch, wie ich überrascht war, als ich sah, dass ein Projekt, das über hundert Bibliotheken eingebunden hatte, irgendwann rund 2 GB belegte...