Состоялся релиз Ruby 3.2.0, динамического объектно-ориентированного языка программирования, отличающегося высокой эффективностью разработки программ и вобравшего в себя лучшие черты Perl, Java, Python, Smalltalk, Eiffel, Ada и Lisp. Код проекта распространяется под лицензиями BSD (“2-clause BSDL”) и “Ruby”, которая ссылается на последний вариант лицензии GPL и полностью совместима с GPLv3.
Основные улучшения:
- Добавлен начальный порт интерпретатора CRuby, компилируемого в промежуточный код WebAssembly для запуската в web-браузере или под управлением обособленных runtime, таких как wasmtime. Для прямого взаимодействия с операционной системой при обособленном запуске используется API WASI (WebAssembly System Interface). Среди прочего предоставлена VFS обвязка поверх WASI, позволяющая упаковывать целиком всё приложение на языке Ruby в представление в виде одного wasm-файла. Запуск в браузере может использоваться для создания обучающих и демонстрационных web-сервисов, таких как TryRuby. На текущем этапе развития порт успешно проходит тестовые наборы basic и bootstrap, в которых не применяется API Thread. В порте также не поддерживаются файберы (Fiber), исключения и сборка мусора.
- Объявлен стабильным и готовым для рабочих применения внутрипроцессный JIT-компилятор YJIT, созданный разработчиками платформы электронной коммерции Shopify в рамках инициативы по увеличению производительности Ruby-программ, использующих фреймворк Rails и вызывающих очень много методов. Ключевым отличием от ранее используемого JIT-компилятора MJIT, базирующегося на обработке методов целиком и использующего внешний компилятор на языке Си, является то, что YJIT применяет версионирование базовых блоков (LBBV – Lazy Basic Block Versioning) и содержит интегрированный JIT-компилятор. Благодаря LBBV, JIT вначале компилирует только начало метода, а оставшуюся часть компилирует через некоторое время, после того как в процессе выполнения будет определены типы используемых переменных и аргументов.
YJIT доступен для архитектур x86-64 и arm64/aarch64 в Linux, MacOS, BSD и других UNIX-платформах.В отличие от СRuby код YJIT написан на языке Rust и требует для компиляции наличие компилятора rustc 1.58.0+, поэтому сборка YJIT по умолчанию отключена и является опциональной. При использовании YJIT зафиксировано увеличение производительности при выполнении теста yjit-bench на 41% по сравнению с использованием интерпретации.
- Добавлена дополнительная защита от атак, вызывающих отказ в обслуживании при обработке внешних данных в неэффективных и длительно выполняемых регулярных выражениях (ReDoS). Значительно улучшен алгоритм сопоставления, в котором задействована техника меморизации. Например, время выполнения выражения ‘/^a*b?a*$/ =~ “a” * 50000 + “x”‘ сократилось с 10 до 0.003 секунд. Ценой оптимизации является увеличение потребления памяти, расход которой примерно в 10 раз выше размера входных данных. Второй мерой защиты является возможность определения таймаута (например, “Regexp.timeout = 1.0”), за который должно успеть обработаться регулярное выражение.
- В состав интегрирован режим syntax_suggest, помогающий диагностировать причину ошибок, связанных с отсутствующим или лишним закрывающим выражением “end” Unmatched ‘end’, missing keyword (‘do’, ‘def’, ‘if’, etc.) ? 1 class Dog > 2 defbark > 3 end 4 end
- В режим выделения места ошибок добавлена возможность пометки аргументов при ошибках, связанных с типами и аргументами, например: test.rb:2:in ‘+’: nil can’t be coerced into Integer (TypeError) sum = ary[0] + ary[1] ^^^^^^
- Добавлен новый синтаксис для перенаправления в другие методы наборов аргументов: def foo(*) bar(*) end def baz(**) quux(**) end
- Предложен вариант старого JIT-компилятора MJIT – ruby_vm/mjit/compiler, реализованный на языке Ruby. Обеспечено выполнение MJIT в отдельном процессе, вместо выполнения в потоке MJIT worker.
- В Bundler 2.4 при обработке зависимостей задействован определитель версий PubGrub, также применяемый в пакетном менеджере pub для языка Dart. Ранее используемый алгоритм Molinillo продолжает применяться в RubyGems, но в будущем также будет заменён на PubGrub.
- Обновлены версии встроенных и входящих в стандартную библиотеку gem-модулей.