Ruby 3.4.0 リリース

Ruby 3.4.0 が公開されました。Ruby 3.4では、ブロックパラメータ参照の it の追加、 デフォルトパーサーのPrismへの変更、Socket ライブラリの Happy Eyeballs Version 2 (RFC 8305) 対応、YJITの改善、 Modular GCの導入など様々な改善が行われています。

it の追加

ブロックパラメータに名前をつけずに参照する it が追加されました。 [Feature #18980]

ary = ["foo", "bar", "baz"]

p ary.map { it.upcase } #=> ["FOO", "BAR", "BAZ"]

it_1 とほとんど同じように動作します。ブロック内で _1 のみを使用する意図がある場合に _1 を使うと、_2_3 などの他の番号付きパラメータが現れる可能性が示唆され、認知的負荷が高い問題がありました。そのため、it は便利なエイリアスとして導入されました。一行ブロックなど、itの意味が一目でわかる簡単なケースにご利用ください。

デフォルトのパーサをPrismに変更

デフォルトで使用するパーサーを parse.y から生成するパーサーから Prism へと変更しました。 [Feature #20564]

これは内部的な改善であり、ユーザーにはほとんど変化が見られないはずです。互換性の問題にお気づきの場合は、ご報告ください。

従来のパーサーを使用するにはコマンドライン引数 --parser=parse.y を使用してください。

Socket ライブラリの Happy Eyeballs Version 2 (RFC 8305) 対応

Socket ライブラリの TCPSocket.new (TCPSocket.open) と Socket.tcp が多数のプログラミング言語で、より良いネットワーク接続の方法として広く標準採用されている Happy Eyeballs Version 2 (RFC 8305) に対応しました。この改善により、Ruby は IPv6 と IPv4 が混在するような最新のインターネット環境においても、効率的で信頼性の高いネットワーク接続が可能となりました。

Ruby 3.3 までは上記の2つのメソッドは名前解決と接続試行をシリアルに実行していました。Happy Eyeballs Version 2 のアルゴリズムでは以下のように実行します。

  1. IPv6とIPv4の名前解決を同時実行する。
  2. 解決されたIPアドレスへの接続を、IPv6を優先して、250ミリ秒間隔で並行して試みる。
  3. 最初に成功した接続を返し、他の接続はキャンセルする。

このアルゴリズムによって、特定のプロトコルや IP アドレスが遅延したり利用できない場合でも、接続遅延を最小限に抑えることが可能となります。

この機能は標準で有効になるため、追加の設定は必要ありません。Ruby 全体で無効にしたい場合は環境変数として RUBY_TCP_NO_FAST_FALLBACK=1 を設定するか、Socket.tcp_fast_fallback=false を Ruby プログラムの中で呼び出してください。またはメソッド単位で無効化する場合、TCPSocket.new (TCPSocket.open) と Socket.tcp のキーワード引数として fast_fallback: false を利用してください。

YJIT

TL;DR

  • x86-64 と arm64 の両方のプラットフォームにおいて、ほとんどのベンチマークのパフォーマンスが向上しました。
  • メタデータの圧縮と統一的なメモリ使用量制限によりメモリ使用量を削減しました。
  • 様々な不具合修正: YJIT はより堅牢になり、より多くの環境でテストされました。

新機能

  • コマンドラインオプション
    • --yjit-mem-size による統一的なメモリ制限が指定可能になりました(デフォルトは 128MiB)。 このオプションはすべての YJIT のメモリ使用量を監視し、従来の --yjit-exec-mem-size オプションよりも直感的に使用できます。
    • --yjit-log オプションを用いて、コンパイルログを監視できるようになりました。
  • Ruby API
    • RubyVM::YJIT.log を用いてコンパイルログの末尾を取得することができるようになりました。
  • YJIT の統計情報
    • RubyVM::YJIT.runtime_stats からインバリデーション、インライン化、メタデータエンコーディングに関する追加の統計情報をいつでも取得できるようになりました。

新しい最適化

  • コンテキストの圧縮化により YJIT のメタデータ保管に必要なメモリを削減しました。
  • ローカル変数やRubyのメソッドの引数のためにレジスタを割り当てるようになりました。
  • YJIT が有効な場合に Ruby で実装されたコアクラスを使うようになりました。
    • Ruby で書き直された Array#each, Array#select, Array#map はより良いパフォーマンスを提供します。 [Feature #20182].
  • 以下のような小さいメソッドをインライン化できるようになりました:
    • 空メソッド
    • 定数を返すメソッド
    • self を返すメソッド
    • 引数を直接返すメソッド
  • 組み込みメソッドに特化したコード生成の対象を広げました
  • String#getbyte, String#setbyte など、String のメソッドの最適化を行いました。
  • 低レベルの bit/byte 操作を高速化するためにビット演算を最適化しました
  • マルチ Ractor モードにおける定数共有をサポートしました。
  • その他、様々な段階的な最適化を行いました。

Modular GC

  • Modular GC 機能により Ruby 標準とは異なる ガベージ・コレクタ (GC) の実装を動的にロードすることができるようになりました。この機能を使うには Ruby をビルドする時に --with-modular-gc を指定してください。GC ライブラリは環境変数 RUBY_GC_LIBRARY を用いて Ruby のランタイムにロードすることができます。[Feature #20351]

  • Ruby 組み込みのガベージ・コレクタは gc/default/default.c ファイルに分割され、 Ruby ランタイムとのやりとりは gc/gc_impl.h に定義される API を用いて行われます。組み込みのガベージコレクタは make modular-gc MODULAR_GC=default というコマンドを用いてライブラリとしてもビルドすることができ、環境変数として RUBY_GC_LIBRARY=default を定義することで有効にすることができます。 [Feature #20470]

  • MMTk をベースとした実験的な GC ライブラリが提供されました。このライブラリはmake modular-gc MODULAR_GC=mmtk コマンドによってビルドし、環境変数 RUBY_GC_LIBRARY=mmtk によって有効化します。この機能を使うにはビルドを行うマシンに Rust のビルドツールを必要とします。 [Feature #20860]

言語機能の変更

  • マジックコメント frozen_string_literal のないファイル中の文字列リテラルは、freeze されているかのように振る舞うようになり、破壊的な変更時に警告を表示するようになりました。これらの警告はコマンドラインオプション -W:deprecated か Ruby プログラムで Warning[:deprecated] = true を指定すると表示されます。 これら無効にするにはコマンドラインオプション --disable-frozen-string-literal を追加して Ruby を実行してください。 [Feature #20205]

  • メソッド呼び出し時の nil 展開キーワードがサポートされました。 **nil**{} と同様に扱われ、キーワードは渡せません。 また、あらゆる変換のためのメソッドも呼ばれません。[Bug #20064]

  • インデックスにブロックを渡せなくなりました。[Bug #19918]

  • インデックスにキーワード引数を渡せなくなりました。[Bug #20218]

  • トップレベルに ::Ruby を予約しました。 Warning[:deprecated] が有効な場合、既に定義済みの場合は警告されます。[Feature #20884]

コアクラスのアップデート

注: 複数のアップデートの中から注目すべきアップデートのみを掲載しています。

  • Exception

    • Exception#set_backtraceThread::Backtrace::Location の配列を受け取れる様になりました。. Kernel#raise, Thread#raiseFiber#raise も同じ配列を受け取れます。[Feature #13557]
  • GC

    • GC.config がガベージ・コレクタの設定変更を可能とするために追加されました。[Feature #20443]

    • GC の設定用のパラメータとして rgengc_allow_full_mark が追加されました。このパラメータを false とすると、GC は young オブジェクトのみを GC 用にマークします。デフォルト値は true です。 [Feature #20443]

  • Ractor

    • Ractor の中で require が可能となりました。この require の処理はメインの Ractor で行われます。 また、メインの Ractor には require 処理のために Ractor._require(feature) が追加されました。 [Feature #20627]

    • Ractor.main? が追加されました。[Feature #20627]

    • 現在実行中の Ractor の Ractor ローカルストレージにアクセスするためのメソッドとして Ractor.[] and Ractor.[]= が追加されました。 [Feature #20715]

    • スレッドセーフに Ractor ローカル変数を初期化するためのメソッド Ractor.store_if_absent(key){ init } が追加されました。 [Feature #20875]

  • Range

    • Range#size は範囲オブジェクトが反復可能ではない場合は TypeError 例外を出すようになりました。[Misc #18984]

標準ライブラリのアップデート

注: 複数のアップデートの中から注目すべき標準ライブラリのアップデートのみを掲載しています。

  • RubyGems
    • gem push コマンドに --attestation オプションが追加されました。このオプションをつけると sigstore に gem の署名情報が保存されます。
  • Bundler
    • ロックファイルの新規作成時に gem の checksum を保存する lockfile_checksums オプションが bundle config に設定可能になりました。
    • 既存のロックファイルに使用している gem の checksum を付与するためのコマンドとして bundle lock --add-checksums が追加されました。
  • JSON

    • JSON.parse が Ruby 3.3 シリーズに添付されている json-2.7.x と比較して 1.5 倍程度高速になりました。
  • Tempfile

    • Tempfile.createanonymous: true キーワードが追加されました。 Tempfile.create(anonymous: true) は作成した一時ファイルを即座に削除します。この機能を用いることで、アプリケーションは独自にファイル削除を行う必要がなくなります。 [Feature #20497]
  • win32/sspi.rb

互換性に関する変更

注: 不具合修正を除きます。

  • エラーメッセージとして表示するバックトレースを変更しました。
    • 開始の引用符は backtick の代わりにシングルクォートを用いるようになりました。[Feature #16495]
    • クラス名が変更しないような場合、メソッド名の前にクラス名を表示するようになりました。[Feature #19117]
    • Kernel#caller, Thread::Backtrace::Location などのメソッドはそれらに応じて変更されました。
    Old:
    test.rb:1:in `foo': undefined method `time' for an instance of Integer
            from test.rb:2:in `<main>'
    
    New:
    test.rb:1:in 'Object#foo': undefined method 'time' for an instance of Integer
            from test.rb:2:in '<main>'
    
  • Hash#inspect の表示が変わりました。[[Bug #20433]]

    • Symbol キーはコロンを用いたモダンな表示になりました: "{user: 1}"
    • 他のキーは従来の '{"user"=>1}' とは異なり、 => の前後にスペースを含む表示になりました: '{"user" => 1}'
  • Kernel#Float() は 10 進表記の小数部がなくても受け付けるようになりました。 [Feature #20705]

    Float("1.")    #=> 1.0 (previously, an ArgumentError was raised)
    Float("1.E-1") #=> 0.1 (previously, an ArgumentError was raised)
    
  • String#to_f は 10 進表記の小数部がなくても受け付けるようになりました。指数を指定すると従来とは結果が変わることに注意してください。 [Feature #20705]

    "1.".to_f    #=> 1.0
    "1.E-1".to_f #=> 0.1 (previously, 1.0 was returned)
    
  • Refinement#refined_class は削除されました。[Feature #19714]

標準ライブラリの互換性の変更

  • DidYouMean

    • DidYouMean::SPELL_CHECKERS[]=DidYouMean::SPELL_CHECKERS.merge! は削除されました。
  • Net::HTTP

    • 2012 年から非推奨とされている以下の定数が削除されました。
      • Net::HTTP::ProxyMod
      • Net::NetPrivate::HTTPRequest
      • Net::HTTPInformationCode
      • Net::HTTPSuccessCode
      • Net::HTTPRedirectionCode
      • Net::HTTPRetriableCode
      • Net::HTTPClientErrorCode
      • Net::HTTPFatalErrorCode
      • Net::HTTPServerErrorCode
      • Net::HTTPResponseReceiver
      • Net::HTTPResponceReceiver
  • Timeout

    • Timeout.timeout が負の値を受け付けなくなりました。[Bug #20795]
  • URI

    • デフォルトのパーサーが RFC 2396 準拠のものから RFC 3986 準拠のものに変わりました。 [Bug #19266]

C API のアップデート

  • rb_newobjrb_newobj_of (と対応するマクロの RB_NEWOBJ, RB_NEWOBJ_OF, NEWOBJ, NEWOBJ_OF) は削除されました。 [Feature #20265]
  • 非推奨とされていた rb_gc_force_recycle は削除されました。 [Feature #18290]

その他の変更点

  • 渡されたブロックを使用しないメソッドにブロックを渡すと、verboseモード(-w) で警告が表示されるようになりました。[Feature #15554]

  • String.freezeInteger#+ のような JIT とインタプリタによって特別に最適化されたメソッドを再定義すると、performance 警告(-W:performance またはWarning[:performance] = true で有効化)が表示されるようになりました。 [Feature #20429]

より詳細な情報は NEWScommit logs を参照してください。

これらの変更により、Ruby 3.3.0から 4942 ファイルが変更され、 202244 行が追加され、 255528 行が削除されました!deletions(-)

メリークリスマス、Ruby 3.4 とともによいお年をお迎えください!

Download

  • https://cache.ruby-lang.org/pub/ruby/3.4/ruby-3.4.0.tar.gz

    SIZE: 23153022
    SHA1: 8ccb561848a7c460ae08e1a120a47c4a88a79335
    SHA256: 068c8523442174bd3400e786f4a6952352c82b1b9f6210fd17fb4823086d3379
    SHA512: bc70ecba27d1cdea00879f03487cad137a7d9ab2ad376cfb7a65780ad14da637fa3944eeeede2c04ab31eeafb970c64ccfeeb854c99c1093937ecc1165731562
    
  • https://cache.ruby-lang.org/pub/ruby/3.4/ruby-3.4.0.tar.xz

    SIZE: 17215572
    SHA1: eb25447cc404e8d2e177c62550d0224ebd410e68
    SHA256: 0081930db22121eb997207f56c0e22720d4f5d21264b5907693f516c32f233ca
    SHA512: 776a2cf3e9ccc77c27500240f168aa3e996b0c7c1ee1ef5a7afc291a06c118444016fde38b5b139c0b800496b8eb1b5456562d833f0edc0658917164763b1af7
    
  • https://cache.ruby-lang.org/pub/ruby/3.4/ruby-3.4.0.zip

    SIZE: 28310193
    SHA1: 26254ca5d3decc28a4e5faec255995265e5270b5
    SHA256: c120228038af04554f6363e716b0a32cbf53cf63c6adf9f2c22a24f43dc8b555
    SHA512: 4d535ed10db76a6aa74f8a025df319deb28483a7a781c24045906ee7663f1cff9d9f9e71dbc993c9e050113a34b37c7fa2143c355a0a6e1e1029bf2c92213ecc
    

What is Ruby

Rubyはまつもとゆきひろ (Matz) によって1993年に開発が始められ、今もオープンソースソフトウェアとして開発が続けられています。Rubyは様々なプラットフォームで動き、世界中で、特にWebアプリケーション開発のために使われています。