Ruby 3.0.0 veröffentlicht

Gepostet von naruse am 25. Dez 2020

Wir freuen uns, die Veröffentlichung von Ruby 3.0.0 bekannt zu geben. Seit 2015 haben wir intensiv auf Ruby 3 hingearbeitet, dessen Ziel Performance, Nebenläufigkeit und Typisierung sind. Insbesondere in Bezug auf die Performance erklärte Matz: „Ruby 3 wird 3-mal schneller sein als Ruby 2“ a.k.a. Ruby 3x3.

Optcarrot 3000 frames

Mit dem Optcarrot-Benchmark, der die Single-Thread-Performance basierend auf der NES-Spieleemulationslast misst, wurde eine 3-mal höhere Leistung als bei Ruby 2.0 erzielt!

Diese wurden in der in benchmark-driver.github.io/hardware.html genannten Umgebung gemessen. Commit 8c510e4095 wurde als Ruby 3.0 verwendet. Abhängig von Ihrer Umgebung oder Ihrem Benchmark ist es möglicherweise nicht 3x schneller.

Ruby 3.0.0 erreicht diese Ziele durch

  • Leistung
    • MJIT
  • Nebenläufigkeit
    • Ractor
    • Fiber Scheduler
  • Typisierung (Statische Analyse)
    • RBS
    • TypeProf

Mit der oben genannten Leistungsverbesserung führt Ruby 3.0 mehrere neue Funktionen ein, die unten beschrieben werden.

Leistung

Als ich "Ruby3x3" zum ersten Mal auf der Konferenz-Keynote ankündigte, dachten viele, einschließlich der Mitglieder des Kernteams, "Matz prahlt." Tatsächlich tat ich das auch. Aber wir haben es geschafft. Ich bin geehrt, dass das Kernteam Ruby 3.0 tatsächlich dreimal schneller als Ruby 2.0 machen konnte (in einigen Benchmarks). – Matz

MJIT

Es wurden viele Verbesserungen in MJIT implementiert. Weitere Einzelheiten finden Sie in NEWS.

Ab Ruby 3.0 soll JIT Leistungsverbesserungen bei begrenzten Workloads erzielen, wie z. B. Spielen (Optcarrot), KI (Rubykon) oder jeder Anwendung, die den Großteil der Zeit mit dem wiederholten Aufruf einiger Methoden verbringt.

Obwohl Ruby 3.0 die Größe des JIT-kompilierten Codes signifikant reduziert hat, ist es noch nicht bereit für die Optimierung von Workloads wie Rails, die oft Zeit mit so vielen Methoden verbringen und daher unter i-cache-Misses leiden, die durch JIT verschärft werden. Bleiben Sie dran für Ruby 3.1 für weitere Verbesserungen bei diesem Problem.

Nebenläufigkeit / Parallelität

Wir leben im Multi-Core-Zeitalter. Nebenläufigkeit ist sehr wichtig. Mit Ractor und Async Fiber wird Ruby zu einer echten nebenläufigen Sprache. — Matz

Ractor (experimentell)

Ractor ist eine Actor-Model-ähnliche Konkurrenz-Abstraktion, die darauf ausgelegt ist, eine parallele Ausführungsfunktion ohne Bedenken hinsichtlich der Thread-Sicherheit bereitzustellen.

Sie können mehrere Ractor erstellen und sie parallel ausführen. Ractor ermöglicht Ihnen, threadsichere parallele Programme zu erstellen, da Ractor keine normalen Objekte teilen kann. Die Kommunikation zwischen Ractor erfolgt durch Nachrichtenaustausch.

Um das Teilen von Objekten einzuschränken, führt Ractor mehrere Einschränkungen für die Ruby-Syntax ein (ohne mehrere Ractor gibt es keine Einschränkung).

Die Spezifikation und Implementierung sind noch nicht ausgereift und können sich in Zukunft ändern. Daher ist diese Funktion als experimentell gekennzeichnet und zeigt die Warnung "experimentelle Funktion" an, wenn die erste Ractor.new auftritt.

Das folgende kleine Programm misst die Ausführungszeit der berühmten Benchmark-Funktion tak (Tak (Funktion) - Wikipedia), indem es sie 4 Mal sequenziell oder 4 Mal parallel mit Ractor ausführt.

def tarai(x, y, z) =
  x <= y ? y : tarai(tarai(x-1, y, z),
                     tarai(y-1, z, x),
                     tarai(z-1, x, y))
require 'benchmark'
Benchmark.bm do |x|
  # sequential version
  x.report('seq'){ 4.times{ tarai(14, 7, 0) } }

  # parallel version
  x.report('par'){
    4.times.map do
      Ractor.new { tarai(14, 7, 0) }
    end.each(&:take)
  }
end
Benchmark result:
          user     system      total        real
seq  64.560736   0.001101  64.561837 ( 64.562194)
par  66.422010   0.015999  66.438009 ( 16.685797)

Das Ergebnis wurde auf Ubuntu 20.04, Intel(R) Core(TM) i7-6700 (4 Kerne, 8 Hardware-Threads) gemessen. Es zeigt, dass die parallele Version 3,87-mal schneller ist als die sequentielle Version.

Weitere Details finden Sie in doc/ractor.md.

Fiber Scheduler

Fiber#scheduler wird zur Abfangung blockierender Operationen eingeführt. Dies ermöglicht leichte Konkurrenz, ohne bestehenden Code ändern zu müssen. Sehen Sie sich "Don’t Wait For Me, Scalable Concurrency for Ruby 3" für einen Überblick über die Funktionsweise an.

Derzeit unterstützte Klassen/Methoden

  • Mutex#lock, Mutex#unlock, Mutex#sleep
  • ConditionVariable#wait
  • Queue#pop, SizedQueue#push
  • Thread#join
  • Kernel#sleep
  • Process.wait
  • IO#wait, IO#read, IO#write und verwandte Methoden (z. B. #wait_readable, #gets, #puts usw.).
  • IO#select wird *nicht unterstützt*.

Dieses Beispielprogramm führt mehrere HTTP-Anfragen gleichzeitig aus

require 'async'
require 'net/http'
require 'uri'

Async do
  ["ruby", "rails", "async"].each do |topic|
    Async do
      Net::HTTP.get(URI "https://www.google.com/search?q=#{topic}")
    end
  end
end

Es verwendet async, das die Ereignisschleife bereitstellt. Diese Ereignisschleife verwendet die Fiber#scheduler Hooks, um Net::HTTP nicht blockierend zu machen. Andere Gems können diese Schnittstelle verwenden, um nicht blockierende Ausführung für Ruby bereitzustellen, und diese Gems können mit anderen Implementierungen von Ruby (z. B. JRuby, TruffleRuby) kompatibel sein, die dieselben nicht blockierenden Hooks unterstützen.

Statische Analyse

Die 2010er Jahre waren ein Zeitalter der statisch typisierten Programmiersprachen. Ruby strebt mit statischer Typüberprüfung, ohne Typdeklaration, unter Verwendung abstrakter Interpretation nach der Zukunft. RBS & TypeProf sind der erste Schritt in die Zukunft. Weitere Schritte werden folgen. — Matz

RBS

RBS ist eine Sprache zur Beschreibung der Typen von Ruby-Programmen.

Typprüfer, einschließlich TypeProf und anderer RBS-unterstützender Tools, werden Ruby-Programme mit RBS-Definitionen viel besser verstehen.

Sie können die Definition von Klassen und Modulen niederschreiben: Methoden, die in der Klasse definiert sind, Instanzvariablen und deren Typen sowie Vererbungs-/Mix-in-Beziehungen.

Ziel von RBS ist die Unterstützung gängiger Muster in Ruby-Programmen und ermöglicht das Schreiben fortgeschrittener Typen, einschließlich Union-Typen, Methodenüberladung und Generics. Es unterstützt auch Duck-Typing mit Interface-Typen.

Ruby 3.0 wird mit dem rbs Gem geliefert, das das Parsen und Verarbeiten von Typdefinitionen in RBS ermöglicht. Das Folgende ist ein kleines Beispiel für RBS mit Klassen-, Modul- und Konstanten-Definitionen.

module ChatApp
  VERSION: String
  class Channel
    attr_reader name: String
    attr_reader messages: Array[Message]
    attr_reader users: Array[User | Bot]              # `|` means union types, `User` or `Bot`.
    def initialize: (String) -> void
    def post: (String, from: User | Bot) -> Message   # Method overloading is supported.
            | (File, from: User | Bot) -> Message
  end
end

Weitere Details finden Sie in der README des rbs Gems.

TypeProf

TypeProf ist ein Typanalysetool, das im Ruby-Paket enthalten ist.

Derzeit dient TypeProf als eine Art Typinferenz.

Es liest normale (nicht typ-annotierte) Ruby-Code, analysiert, welche Methoden definiert sind und wie sie verwendet werden, und generiert einen Prototyp einer Signatur im RBS-Format.

Hier ist eine einfache Demo von TypeProf.

Ein Beispiel-Input

# test.rb
class User
  def initialize(name:, age:)
    @name, @age = name, age
  end
  attr_reader :name, :age
end
User.new(name: "John", age: 20)

Ein Beispiel-Output

$ typeprof test.rb
# Classes
class User
  attr_reader name : String
  attr_reader age : Integer
  def initialize : (name: String, age: Integer) -> [String, Integer]
end

Sie können TypeProf ausführen, indem Sie die Eingabe als "test.rb" speichern und den Befehl "typeprof test.rb" aufrufen.

Sie können TypeProf auch online ausprobieren. (Es führt TypeProf serverseitig aus, also sorry, wenn es nicht verfügbar ist!)

Weitere Einzelheiten finden Sie in der TypeProf-Dokumentation und in den Demos.

TypeProf ist experimentell und noch nicht sehr ausgereift; nur eine Teilmenge der Ruby-Sprache wird unterstützt und die Erkennung von Typfehlern ist begrenzt. Aber es wächst immer noch rasant, um die Abdeckung von Sprachfunktionen, die Analyseleistung und die Benutzerfreundlichkeit zu verbessern. Jedes Feedback ist sehr willkommen.

Weitere bemerkenswerte neue Funktionen

  • Die einzeilige Mustererkennung wurde neu gestaltet. (experimentell)

    • => wurde hinzugefügt. Es kann wie eine rechtsgerichtete Zuweisung verwendet werden.

      0 => a
      p a #=> 0
      
      {b: 0, c: 1} => {b:}
      p b #=> 0
      
    • in gibt jetzt true oder false zurück.

      # version 3.0
      0 in 1 #=> false
      
      # version 2.7
      0 in 1 #=> raise NoMatchingPatternError
      
  • Die Suchmustererkennung wurde hinzugefügt. (experimentell)

    case ["a", 1, "b", "c", 2, "d", "e", "f", 3]
    in [*pre, String => x, String => y, *post]
      p pre  #=> ["a", 1]
      p x    #=> "b"
      p y    #=> "c"
      p post #=> [2, "d", "e", "f", 3]
    end
    
  • Endless-Methodendefinition wurde hinzugefügt.

    def square(x) = x * x
    
  • Hash#except ist jetzt integriert.

    h = { a: 1, b: 2, c: 3 }
    p h.except(:a) #=> {:b=>2, :c=>3}
    
  • Memory View wird als experimentelle Funktion hinzugefügt

    • Dies ist ein neuer C-API-Satz zum Austausch eines rohen Speicherbereichs, wie z. B. eines numerischen Arrays oder eines Bitmap-Bildes, zwischen Erweiterungsbibliotheken. Die Erweiterungsbibliotheken können auch die Metadaten des Speicherbereichs austauschen, die aus Form, Elementformat usw. bestehen. Mit diesen Arten von Metadaten können die Erweiterungsbibliotheken selbst ein mehrdimensionales Array ordnungsgemäß austauschen. Dieses Feature wurde unter Bezugnahme auf das Pufferprotokoll von Python entwickelt.

Leistungsverbesserungen

  • Das Einfügen langer Codes in IRB ist 53-mal schneller als in der mit Ruby 2.7.0 gebündelten Version. Beispielsweise dauert das Einfügen von diesem Beispielcode von 11,7 Sekunden auf 0,22 Sekunden.
  • Der Befehl measure wurde zu IRB hinzugefügt. Er ermöglicht einfache Messung der Ausführungszeit.

    irb(main):001:0> 3
    => 3
    irb(main):002:0> measure
    TIME is added.
    => nil
    irb(main):003:0> 3
    processing time: 0.000058s
    => 3
    irb(main):004:0> measure :off
    => nil
    irb(main):005:0> 3
    => 3
    

Weitere bemerkenswerte Änderungen seit 2.7

  • Schlüsselwortargumente wurden von anderen Argumenten getrennt.
    • Grundsätzlich funktioniert Code, der unter Ruby 2.7 eine Warnung ausgibt, nicht mehr. Weitere Einzelheiten finden Sie in diesem Dokument.
    • Übrigens unterstützt die Argumentenweiterleitung jetzt führende Argumente.

      def method_missing(meth, ...)
        send(:"do_#{ meth }", ...)
      end
      
  • Mustererkennung (case/in) ist nicht mehr experimentell.
  • Das $SAFE Feature wurde vollständig entfernt; es ist jetzt eine normale globale Variable.
  • Die Reihenfolge der Rückverfolgungen wurde mit Ruby 2.5 umgekehrt; diese Änderung wurde rückgängig gemacht. Rückverfolgungen verhalten sich jetzt wie unter Ruby 2.4: Eine Fehlermeldung und die Zeilennummer, bei der die Ausnahme auftritt, werden zuerst ausgegeben, und ihre Aufrufer werden später ausgegeben.
  • Einige Standardbibliotheken wurden aktualisiert.
    • RubyGems 3.2.3
    • Bundler 2.2.3
    • IRB 1.3.0
    • Reline 0.2.0
    • Psych 3.3.0
    • JSON 2.5.1
    • BigDecimal 3.0.0
    • CSV 3.1.9
    • Date 3.1.0
    • Digest 3.0.0
    • Fiddle 1.0.6
    • StringIO 3.0.0
    • StringScanner 3.0.0
    • usw.
  • Die folgenden Bibliotheken sind keine gebündelten Gems oder Standardbibliotheken mehr. Installieren Sie die entsprechenden Gems, um diese Funktionen zu nutzen.
    • sdbm
    • webrick
    • net-telnet
    • xmlrpc
  • Die folgenden Standard-Gems sind nun gebündelte Gems.
    • rexml
    • rss
  • Die folgenden Standardbibliotheksdateien sind nun Standard-Gems und werden auf rubygems.org veröffentlicht.
    • English
    • abbrev
    • base64
    • drb
    • debug
    • erb
    • find
    • net-ftp
    • net-http
    • net-imap
    • net-protocol
    • open-uri
    • optparse
    • pp
    • prettyprint
    • resolv-replace
    • resolv
    • rinda
    • set
    • securerandom
    • shellwords
    • tempfile
    • tmpdir
    • time
    • tsort
    • un
    • weakref
    • digest
    • io-nonblock
    • io-wait
    • nkf
    • pathname
    • syslog
    • win32ole

Weitere Einzelheiten finden Sie in NEWS oder in den Commit-Logs.

Mit diesen Änderungen wurden seit Ruby 2.7.0 4028 Dateien geändert, 200058 Einfügungen(+), 154063 Löschungen(-)!

Ruby 3.0 ist ein Meilenstein. Die Sprache hat sich weiterentwickelt und die Kompatibilität beibehalten. Aber es ist nicht das Ende. Ruby wird sich weiterentwickeln und noch besser werden. Bleiben Sie dran! — Matz

Frohe Weihnachten, frohe Feiertage und viel Spaß beim Programmieren mit Ruby 3.0!

Herunterladen

  • https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.gz

    SIZE: 19539509
    SHA1: 233873708c1ce9fdc295e0ef1c25e64f9b98b062
    SHA256: a13ed141a1c18eb967aac1e33f4d6ad5f21be1ac543c344e0d6feeee54af8e28
    SHA512: e62f4f63dc12cff424e8a09adc06477e1fa1ee2a9b2b6e28ca22fd52a211e8b8891c0045d47935014a83f2df2d6fc7c8a4fd87f01e63c585afc5ef753e1dd1c1
    
  • https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.xz

    SIZE: 14374176
    SHA1: c142899d70a1326c5a71311b17168f98c15e5d89
    SHA256: 68bfaeef027b6ccd0032504a68ae69721a70e97d921ff328c0c8836c798f6cb1
    SHA512: 2a23c2894e62e24bb20cec6b2a016b66d7df05083668726b6f70af8338211cfec417aa3624290d1f5ccd130f65ee7b52b5db7d428abc4a9460459c9a5dd1a450
    
  • https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.zip

    SIZE: 23862057
    SHA1: 2a9629102d71c7fe7f31a8c91f64e570a40d093c
    SHA256: a5e4fa7dc5434a7259e9a29527eeea2c99eeb5e82708f66bb07731233bc860f4
    SHA512: e5bf742309d79f05ec1bd1861106f4b103e4819ca2b92a826423ff451465b49573a917cb893d43a98852435966323e2820a4b9f9377f36cf771b8c658f80fa5b
    

Was ist Ruby

Ruby wurde 1993 von Matz (Yukihiro Matsumoto) entwickelt und wird nun als Open Source entwickelt. Es läuft auf mehreren Plattformen und wird weltweit eingesetzt, insbesondere für die Webentwicklung.

Aktuelle Nachrichten

Ruby 4.0.0 veröffentlicht

Wir freuen uns, die Veröffentlichung von Ruby 4.0.0 bekannt zu geben. Ruby 4.0 führt „Ruby Box“ und „ZJIT“ ein und bringt viele Verbesserungen mit sich.

Veröffentlicht von naruse am 25. Dez 2025

Ein neuer Look für Rubys Dokumentation

Nach dem Redesign von ruby-lang.org gibt es weitere Neuigkeiten zur Feier des 30-jährigen Jubiläums von Ruby: docs.ruby-lang.org hat ein komplett neues Erscheinungsbild mit Aliki – dem neuen Standard-Theme von RDoc.

Veröffentlicht von Stan Lo am 23. Dez 2025

Neues Website-Erscheinungsbild

Wir freuen uns, ein umfassendes Redesign unserer Website bekannt zu geben. Das Design für dieses Update wurde von Taeko Akatsuka erstellt.

Veröffentlicht von Hiroshi SHIBATA am 22. Dez 2025

Ruby 4.0.0 preview3 veröffentlicht

Wir freuen uns, die Veröffentlichung von Ruby 4.0.0-preview3 bekannt zu geben. Ruby 4.0 führt Ruby::Box und „ZJIT“ ein und bringt viele Verbesserungen mit sich.

Veröffentlicht von naruse am 18. Dez 2025

Weitere Neuigkeiten...