Вийшов Ruby 3.0.0
Опублікував naruse 25-12-2020
Переклав: Andrii Furmanets
Ми раді повідомити про реліз Ruby 3.0.0. Починаючи з 2015 року, ми наполегливо працювали над Ruby 3, метою якого є продуктивність, паралелізм і типізація. Особливо щодо продуктивності, Matz заявив: «Ruby3 буде в 3 рази швидшим за Ruby2» — так звана ініціатива Ruby 3x3.

З бенчмарком Optcarrot, який вимірює однопотокову продуктивність на основі емуляції ігор NES, він досяг у 3 рази кращої продуктивності, ніж Ruby 2.0!
Ruby 3.0.0 досягає цих цілей завдяки:
- Продуктивність
- MJIT
- Паралелізм
- Ractor
- Fiber Scheduler
- Типізація (Статичний аналіз)
- RBS
- TypeProf
З наведеним вище покращенням продуктивності Ruby 3.0 вводить кілька нових функцій, описаних нижче.
Продуктивність
Коли я вперше оголосив «Ruby3x3» на конференції, багато хто, включаючи членів основної команди, вважав: «Матц хвалько». Насправді я й сам так думав. Але ми це зробили. Я радий бачити, що основна команда справді змогла зробити Ruby 3.0 утричі швидшим за Ruby 2.0 (в деяких бенчмарках). — Matz
MJIT
Було впроваджено багато покращень у MJIT. Докладніше див. у NEWS.
Станом на Ruby 3.0, JIT має покращувати продуктивність в обмежених сценаріях, таких як ігри (Optcarrot), ШІ (Rubykon) або будь-який застосунок, який витрачає більшість часу на виклик кількох методів багато разів.
Хоча Ruby 3.0 значно зменшив розмір JIT-коду, він ще не готовий для оптимізації таких навантажень, як Rails, які часто витрачають час на багато методів і тому страждають від промахів i-cache, погіршених JIT. Очікуйте подальших покращень у Ruby 3.1.
Паралелізм
Сьогодні ера багатоядерних процесорів. Паралелізм дуже важливий. З Ractor разом з асинхронним Fiber Ruby стане справжньою паралельною мовою. — Matz
Ractor (експериментальний)
Ractor — це абстракція паралелізму на зразок моделі акторів, розроблена для забезпечення можливості паралельного виконання без проблем із безпекою потоків.
Ви можете створювати кілька ракторів і запускати їх паралельно. Ractor дозволяє створювати потокобезпечні паралельні програми, оскільки рактори не можуть ділитися звичайними об’єктами. Комунікація між ракторами здійснюється через обмін повідомленнями.
Щоб обмежити спільне використання об’єктів, Ractor вводить кілька обмежень до синтаксису Ruby (без кількох ракторів обмежень немає).
Специфікація та реалізація ще не дозріли і можуть змінитися в майбутньому, тому цю функцію позначено як експериментальну, і при першому Ractor.new з’являється попередження «experimental feature».
Наступна невелика програма вимірює час виконання відомої функції бенчмарку tak (Tak (function) - Wikipedia), виконуючи її 4 рази послідовно або 4 рази паралельно з ракторами.
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|
# послідовна версія
x.report('seq'){ 4.times{ tarai(14, 7, 0) } }
# паралельна версія
x.report('par'){
4.times.map do
Ractor.new { tarai(14, 7, 0) }
end.each(&:take)
}
end
Результат бенчмарку:
user system total real
seq 64.560736 0.001101 64.561837 ( 64.562194)
par 66.422010 0.015999 66.438009 ( 16.685797)
Результат отримано на Ubuntu 20.04, Intel(R) Core(TM) i7-6700 (4 ядра, 8 апаратних потоків). Паралельна версія в 3.87 разів швидша за послідовну.
Докладніше див. doc/ractor.md.
Fiber Scheduler
Fiber#scheduler введено для перехоплення блокувальних операцій. Це дозволяє реалізувати легку конкурентність без зміни існуючого коду. Перегляньте «Don’t Wait For Me, Scalable Concurrency for Ruby 3» для огляду того, як це працює.
Підтримувані класи/методи:
Mutex#lock,Mutex#unlock,Mutex#sleepConditionVariable#waitQueue#pop,SizedQueue#pushThread#joinKernel#sleepProcess.waitIO#wait,IO#read,IO#writeта пов’язані методи (напр.,#wait_readable,#gets,#putsтощо).IO#selectне підтримується.
Ця приклад-програма виконує кілька HTTP-запитів паралельно:
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
Вона використовує async, що надає цикл подій. Цей цикл подій використовує хуки Fiber#scheduler, щоб зробити Net::HTTP неблокувальним. Інші геми можуть використовувати цей інтерфейс для неблокувального виконання в Ruby.
Статичний аналіз
2010-і були ерою статично типізованих мов програмування. Ruby шукає майбутнє зі статичною перевіркою типів без оголошення типів, використовуючи абстрактну інтерпретацію. RBS і TypeProf — перші кроки до цього майбутнього. Більше кроків попереду. — Matz
RBS
RBS — це мова для опису типів програм Ruby.
Перевірники типів, включаючи TypeProf та інші інструменти з підтримкою RBS, краще розумітимуть програми Ruby з визначеннями RBS.
Ви можете записати визначення класів і модулів: методи, визначені в класі, змінні екземпляра та їхні типи, а також відносини наслідування/міксинів.
Мета RBS — підтримувати типові патерни в програмах Ruby та дозволяти записувати розширені типи, включаючи типи-об’єднання, перевантаження методів і генерики. Він також підтримує duck typing за допомогою інтерфейсних типів.
Ruby 3.0 поставляється з гемом rbs, який дозволяє парсити та обробляти визначення типів, записані в RBS.
Ось невеликий приклад RBS з визначеннями класу, модуля та константи.
module ChatApp
VERSION: String
class Channel
attr_reader name: String
attr_reader messages: Array[Message]
attr_reader users: Array[User | Bot] # `|` означає типи-об'єднання, `User` або `Bot`.
def initialize: (String) -> void
def post: (String, from: User | Bot) -> Message # Підтримується перевантаження методів.
| (File, from: User | Bot) -> Message
end
end
Докладніше див. README гема rbs.
TypeProf
TypeProf — інструмент аналізу типів, що входить до пакету Ruby.
Наразі TypeProf працює як виведення типів.
Він читає звичайний (без анотацій типів) код Ruby, аналізує, які методи визначено та як вони використовуються, і генерує прототип сигнатури типу у форматі RBS.
Ось коротка демонстрація TypeProf.
Приклад вхідних даних:
# test.rb
class User
def initialize(name:, age:)
@name, @age = name, age
end
attr_reader :name, :age
end
User.new(name: "John", age: 20)
Приклад виводу:
$ typeprof test.rb
# Classes
class User
attr_reader name : String
attr_reader age : Integer
def initialize : (name: String, age: Integer) -> [String, Integer]
end
Ви можете запустити TypeProf, зберігши вхідні дані як «test.rb» і виконавши команду «typeprof test.rb».
Ви також можете спробувати TypeProf онлайн. (Він виконує TypeProf на сервері, тож вибачте, якщо не працює!)
Докладніше див. документацію TypeProf та демо.
TypeProf експериментальний і ще не дозрілий; підтримується лише підмножина мови Ruby, а виявлення помилок типів обмежене. Проте він швидко розвивається. Будь-який зворотний зв’язок вітається.
Інші важливі нові функції
-
Однорядкове зіставлення шаблонів перероблено. (експериментально)
-
Додано
=>. Можна використовувати як присвоєння справа наліво.0 => a p a #=> 0 {b: 0, c: 1} => {b:} p b #=> 0 -
inтепер повертаєtrueабоfalse.# версія 3.0 0 in 1 #=> false # версія 2.7 0 in 1 #=> raise NoMatchingPatternError
-
-
Додано Find-патерн. (експериментально)
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 -
Додано безкінечне визначення методу.
def square(x) = x * x -
Hash#exceptтепер вбудовано.h = { a: 1, b: 2, c: 3 } p h.except(:a) #=> {:b=>2, :c=>3} -
Memory view додано як експериментальну функцію.
Покращення продуктивності
- Вставка довгого коду в IRB стала в 53 рази швидшою, ніж у версії з Ruby 2.7.0.
Інші важливі зміни порівняно з 2.7
- Ключові аргументи відокремлено від інших аргументів.
- Код, що виводить попередження в Ruby 2.7, не працюватиме. Докладніше див. цей документ.
- До речі, передача аргументів тепер підтримує початкові аргументи.
- Зіставлення шаблонів (
case/in) більше не експериментальне. - Функцію
$SAFEповністю видалено; тепер це звичайна глобальна змінна. - Деякі стандартні бібліотеки оновлено.
- Наступні бібліотеки більше не є bundled gems або стандартними бібліотеками: sdbm, webrick, net-telnet, xmlrpc.
Докладніше див. NEWS або історію комітів.
Ruby3.0 — це віха. Мова еволюціонувала, зберігаючи сумісність. Але це не кінець. Ruby продовжить розвиватися і ставатиме ще кращим. Слідкуйте за новинами! — Matz
Веселого Різдва, гарних свят і насолоджуйтесь програмуванням з Ruby 3.0!
Завантаження
-
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
Що таке Ruby
Ruby вперше розробив Matz (Yukihiro Matsumoto) у 1993 році, і зараз розвивається як Open Source. Він працює на багатьох платформах і використовується по всьому світу, особливо для веброзробки.
Останні новини
Оновлення айдентики нашого сайту
Раді оголосити про комплексне оновлення нашого сайту. Дизайн для цього оновлення створила Taeko Akatsuka.
Опублікував Hiroshi SHIBATA 22-12-2025
Вийшов Ruby 4.0.0 preview3
Раді повідомити про вихід Ruby 4.0.0-preview3. Ruby 4.0 вводить Ruby::Box і “ZJIT” та додає багато покращень.
Опублікував naruse 18-12-2025
Вийшов Ruby 3.4.8
Вийшов Ruby 3.4.8.
Опублікував k0kubun 17-12-2025
Вийшов Ruby 4.0.0 preview2
Раді повідомити про вихід Ruby 4.0.0-preview2. Ruby 4.0 оновлює версію Unicode до 17,0.0 тощо.
Опублікував naruse 17-11-2025