IronRuby 4.0.5: Ruby 4.0 auf .NET 10 und .NET 11
Ende September habe ich über IronRuby 4.0 geschrieben, meinen Fork, der IronRuby auf Ruby 4.0 bringt, mit prism als Parser. Damals lief es auf .NET 8, und der erste Download hiess 4.0.0-preview1. Sechs Wochen und sechs Versionen später ist IronRuby 4.0.5 erschienen. Es ist die erste Version, die auf .NET 10 und .NET 11 läuft, und die erste ohne .NET 8.
$ ./ironruby -e 'puts RUBY_DESCRIPTION'
IronRuby 4.0.5 (4.0.0) on .NET 10.0.15 [x86_64-linux]
Warum .NET 8 gehen musste
Microsofts Support für .NET 8 ist gestern, am 10. November 2026, ausgelaufen. 4.0.4 war die letzte Version dafür. Ab 4.0.5 baut IronRuby für net10.0 und net11.0, und der Code, den nur .NET 8 brauchte, ist entfernt.
Jeden Download gibt es jetzt in zwei Varianten:
- .NET 10, der Standard. Die Dateien behalten die Namen der früheren Versionen, zum Beispiel
ironruby-4.0.5-linux-x64.tar.gz, und auch der Windows-Installer nutzt diese Variante. .NET 10 ist eine LTS-Version mit Support bis zum 14. November 2028. - .NET 11, mit
-net11-im Namen, für Linux, Windows und macOS. Dafür gibt es keinen Installer.
Beide bringen ihre eigene Laufzeitumgebung mit, für Ruby-Skripte muss man also kein .NET installieren. Nur ein Programm, das IronRuby einbettet oder seine Assemblies lädt, braucht jetzt .NET 10 oder neuer.
Auf .NET 11 startet IronRuby etwa 5 % schneller, und die Benchmark-Sammlung von TruffleRuby läuft etwa 3,5 % schneller. Der Standard bleibt .NET 10, weil es die LTS-Version ist.
Mit der Laufzeitumgebung ändern sich zwei kleine Dinge. Ein Integer kann nicht mehr breiter als etwa 2**31 Bit sein, weil das seit .NET 9 die Grenze von .NETs BigInteger ist. 1 << 2**31 wirft jetzt NoMemoryError, wie CRuby, wenn eine Speicheranforderung scheitert. Und unter Windows nutzt zlib jetzt das zlib-ng in .NET. Zlib::ZLIB_VERSION ändert sich deshalb, und komprimierte Bytes können sich von 4.0.4 unterscheiden. Entpackt ergeben sie dasselbe.
Was seit September passiert ist
4.0.5 selbst ist eine kleine Version. Die grösseren Änderungen kamen in den vier Versionen davor. Hier die, die ich am wichtigsten finde.
Rails mit SQLite, auch unter Windows
Sam Ruby (@rubys) hat Rails-Apps laufen lassen, die sein Projekt Roundhouse transpiliert, und dabei die ersten Fehler gefunden: Pipes und Sockets unter macOS, wo Puma nicht starten konnte, IO#write_nonblock, das grosse Antworten abschnitt, und einen SQLite-Absturz unter Linux. Alle drei sind seit 4.0.1 behoben.
Mit 4.0.2 läuft eine Rails-8.1-App mit SQLite unter Windows: gem install rails, rails new, ein Scaffold, Migrationen, Turbo und Stimulus und bin/rails server auf Puma. In einem Test beliebter Gems unter Windows lieferten 81 dieselbe Ausgabe wie CRuby, Byte für Byte, darunter rubocop, rspec, pry und prawn. Auch TLS funktioniert, in net/http und in Puma.
Ein Windows-Installer und irb
Seit 4.0.3 gibt es einen Windows-Installer im Stil von RubyInstaller. Er installiert nach C:\IronRuby40-x64, braucht keine Adminrechte und legt ironruby, iirb und igem in den PATH. irb und gem bleiben die von CRuby, so können beide nebeneinander leben.
irb funktioniert unter Windows jetzt wie in CRuby, mit Farben, typbasierter Vervollständigung und korrekt angezeigten Umlauten in der Konsole. Und der Interpreter heisst jetzt ironruby, so wie der von JRuby jruby heisst. Ohne Skript in einem Terminal gestartet, öffnet er irb.
.NET so, wie man Ruby 4 schreibt
.NET aufzurufen ist viel angenehmer geworden. Keyword-Argumente werden über den Namen an .NET-Parameter gebunden, und ein Block geht an einen Delegate-Parameter. list.Sort { |a, b| b <=> a } und Task.Run { } funktionieren einfach.
Dank @sholden nimmt using jetzt auch einen .NET-Namespace, wie die using-Direktive in C#. Seine Erweiterungsmethoden gelten dann nur für den Rest der Datei:
using System::Linq
list = System::Collections::Generic::List[Integer].new([3, 1, 2])
p list.where { it > 1 }.order_by { -it }.to_a # => [3, 2]
Die 101 LINQ-Beispiele laufen in der CI.
Viel schneller
Bei 4.0.4 ging es vor allem um Geschwindigkeit. Eine Reihe von Benchmarks hatte die Stellen aufgelistet, an denen IronRuby weit hinter CRuby lag, und die meisten davon sind jetzt geschlossen oder viel kleiner:
- Eine gefangene Exception kostet etwa ein Viertel von vorher.
- Einen langen String zu kopieren dauert konstant lange:
s.dupvon 100 KB ging von 83 auf 0,3 µs. RationalundComplexsind in C# geschrieben:Rational(1, 3)ging von 540 auf 49 ns, schneller als CRuby.- lobsters aus ruby-bench läuft 31 bis 38 % schneller, und das Dekodieren in protoboeuf ging von 81 s auf 1,3 s.
- Mit einem Doom-Renderer in Ruby dauert ein Bild 16 bis 18 ms statt etwa 27 ms. CRuby ohne YJIT braucht 22 bis 25 ms.
Der Schwachpunkt bleiben Exceptions: Eine zu werfen kostet einige zehn Mikrosekunden, gegenüber 1 bis 6 in CRuby, wegen der Art, wie .NET Exceptions behandelt.
Näher an CRuby
Noch ein paar Dinge, mit denen sich IronRuby wie CRuby 4.0 verhält:
- Tiefe Rekursion wirft einen
SystemStackError, den man fangen kann. Vorher beendete sie den Prozess. Ractorist da, mit der API von Ruby 4.0. 146 der 153 Prüfungen aus den Ractor-Tests von CRuby bestehen.- Fehlermeldungen sehen aus wie in CRuby, mit error_highlight und den annotierten Syntaxfehlern von prism.
- Fehlermeldungen setzen Namen in
'solche Anführungszeichen', wie CRuby seit 3.4. - Mehr Gems mit C-Erweiterungen funktionieren, weil ihre Erweiterung nach C# portiert ist, etwa strptime, yajl-ruby und zstd-ruby. 34 der 36 grösseren Benchmarks aus ruby-bench laufen.
Danke
IronRuby hat seine ersten Beiträge von aussen bekommen. Danke an Sam Ruby für die Fixes für macOS und Sockets, an @khasinski für File#flock unter macOS und ir -S, und an @sholden für Refinements, LINQ, Threads und vieles mehr.
Ausprobieren
Auf der Release-Seite gibt es die Downloads für Linux x64, Windows x64 und macOS auf Apple Silicon. Unter Windows geht es am einfachsten mit dem Installer, ironruby-4.0.5-win-x64-setup.exe. Sonst das Archiv entpacken:
$ tar xzf ironruby-4.0.5-linux-x64.tar.gz
$ cd ironruby-4.0.5-linux-x64
$ ./ironruby
$ ./ironruby script.rb
$ ./igem.sh install rack
Jede Datei hat eine signierte Build-Provenance-Attestation. Damit kann man prüfen, welcher Workflow sie aus welchem Commit gebaut hat:
$ gh attestation verify ironruby-4.0.5-linux-x64.tar.gz --repo Largo/ironruby
Die macOS-Builds entstehen in der CI, aber ich habe sie noch kaum getestet. Wenn du IronRuby ausprobierst und etwas nicht geht, eröffne bitte ein Issue oder schreib mir.