IronRuby 4.0.5: Ruby 4.0 su .NET 10 e .NET 11
A fine settembre ho scritto di IronRuby 4.0, il mio fork che porta IronRuby a Ruby 4.0, con prism come parser. Allora girava su .NET 8 e il primo download si chiamava 4.0.0-preview1. Sei settimane e sei release dopo è uscito IronRuby 4.0.5. È la prima release che gira su .NET 10 e .NET 11, e la prima senza .NET 8.
$ ./ironruby -e 'puts RUBY_DESCRIPTION'
IronRuby 4.0.5 (4.0.0) on .NET 10.0.15 [x86_64-linux]
Perché .NET 8 doveva andarsene
Il supporto di Microsoft per .NET 8 è terminato ieri, il 10 novembre 2026. La 4.0.4 era l’ultima release per .NET 8. Dalla 4.0.5 IronRuby si compila per net10.0 e net11.0, e il codice che serviva solo a .NET 8 è stato rimosso.
Ogni download ora esiste in due versioni:
- .NET 10, quella predefinita. I file mantengono i nomi delle release precedenti, come
ironruby-4.0.5-linux-x64.tar.gz, e anche l’installer per Windows usa questa versione. .NET 10 è una release LTS, supportata fino al 14 novembre 2028. - .NET 11, con
-net11-nel nome, per Linux, Windows e macOS. Per questa non c’è un installer.
Entrambe portano con sé il proprio runtime, quindi per eseguire script Ruby non serve installare .NET. Solo un programma che integra IronRuby, o ne carica gli assembly, ora ha bisogno di .NET 10 o successivo.
Su .NET 11 l’avvio è più breve di circa il 5 %, e la raccolta di benchmark di TruffleRuby gira circa il 3,5 % più veloce. La versione predefinita resta .NET 10, perché è la release LTS.
Con il runtime cambiano due piccole cose. Un Integer non può più superare circa 2**31 bit, perché da .NET 9 questo è il limite del BigInteger di .NET. 1 << 2**31 ora solleva NoMemoryError, come fa CRuby quando un’allocazione fallisce. E su Windows zlib ora usa lo zlib-ng incluso in .NET: Zlib::ZLIB_VERSION cambia e i byte compressi possono essere diversi da quelli della 4.0.4. Decompressi, danno lo stesso risultato.
Cosa è successo da settembre
La 4.0.5 in sé è una release piccola. I cambiamenti più grandi sono arrivati nelle quattro release precedenti. Ecco quelli che trovo più importanti.
Rails con SQLite, anche su Windows
Sam Ruby (@rubys) ha fatto girare app Rails che il suo progetto Roundhouse transpila, e ha trovato i primi bug: pipe e socket su macOS, dove Puma non partiva, IO#write_nonblock, che troncava le risposte grandi, e un crash di SQLite su Linux. Tutti e tre sono corretti dalla 4.0.1.
Con la 4.0.2 un’app Rails 8.1 gira con SQLite su Windows: gem install rails, rails new, uno scaffold, migrazioni, Turbo e Stimulus, e bin/rails server su Puma. In un test di gem popolari su Windows, 81 hanno dato lo stesso output di CRuby, byte per byte, tra cui rubocop, rspec, pry e prawn. Funziona anche TLS, sia in net/http che in Puma.
Un installer per Windows e irb
Dalla 4.0.3 c’è un installer per Windows nello stile di RubyInstaller. Installa in C:\IronRuby40-x64, funziona senza diritti di amministratore e mette ironruby, iirb e igem nel PATH. irb e gem restano quelli di CRuby, così i due possono convivere.
irb ora funziona su Windows come in CRuby, con i colori, il completamento basato sui tipi e le lettere accentate mostrate correttamente nella console. E l’interprete ora si chiama ironruby, come quello di JRuby si chiama jruby. Avviato in un terminale senza script, apre irb.
.NET come si scrive Ruby 4
Chiamare .NET è diventato molto più piacevole. Gli argomenti keyword si legano ai parametri .NET per nome, e un blocco va a un parametro di tipo delegate: list.Sort { |a, b| b <=> a } e Task.Run { } funzionano e basta.
Grazie a @sholden, using ora accetta anche un namespace .NET, come la direttiva using di C#. I suoi metodi di estensione valgono solo per il resto del file:
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]
I 101 esempi LINQ girano nella CI.
Molto più veloce
La 4.0.4 riguardava soprattutto la velocità. Una serie di benchmark aveva elencato i punti in cui IronRuby era molto indietro rispetto a CRuby, e la maggior parte ora è chiusa o molto ridotta:
- Un’eccezione catturata costa circa un quarto di prima.
- Copiare una String lunga richiede un tempo costante:
s.dupdi 100 KB è passato da 83 a 0,3 µs. RationaleComplexsono scritti in C#:Rational(1, 3)è passato da 540 a 49 ns, più veloce di CRuby.- lobsters di ruby-bench gira dal 31 al 38 % più veloce, e la decodifica di protoboeuf è passata da 81 s a 1,3 s.
- Con un renderer di Doom in Ruby un fotogramma richiede da 16 a 18 ms invece di circa 27 ms. CRuby senza YJIT ne impiega da 22 a 25.
Il punto debole restano le eccezioni: sollevarne una costa decine di microsecondi, contro 1–6 in CRuby, per il modo in cui .NET gestisce le eccezioni.
Più vicino a CRuby
Ancora qualche punto in cui IronRuby ora si comporta come CRuby 4.0:
- Una ricorsione profonda solleva un
SystemStackErrorche si può catturare. Prima terminava il processo. - C’è
Ractor, con l’API di Ruby 4.0. Passano 146 dei 153 controlli dei test Ractor di CRuby. - I messaggi di errore sono come quelli di CRuby, con error_highlight e gli errori di sintassi annotati di prism.
- I messaggi di errore citano i nomi
'così', come CRuby dalla 3.4. - Funzionano più gem con estensioni C, perché la loro estensione è stata portata in C#, per esempio strptime, yajl-ruby e zstd-ruby. Girano 34 dei 36 benchmark più grandi di ruby-bench.
Grazie
IronRuby ha ricevuto i suoi primi contributi dall’esterno. Grazie a Sam Ruby per le correzioni su macOS e sui socket, a @khasinski per File#flock su macOS e ir -S, e a @sholden per i refinement, LINQ, i thread e molto altro.
Provarlo
La pagina della release ha i download per Linux x64, Windows x64 e macOS su Apple silicon. Su Windows il modo più semplice è l’installer, ironruby-4.0.5-win-x64-setup.exe. Altrove basta estrarre l’archivio:
$ 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
Ogni file ha un’attestazione di provenienza firmata, con cui si può verificare quale workflow l’ha creato e da quale commit:
$ gh attestation verify ironruby-4.0.5-linux-x64.tar.gz --repo Largo/ironruby
Le build per macOS vengono create nella CI, ma non le ho ancora testate quasi per niente. Se provi IronRuby e qualcosa non funziona, apri una issue o scrivimi.