Сегодня на официальном сайте проекта Rubinius появилась отличная новость о выходе версии 2.0 и о планах проекта на будущее. Rubinius — это альтернативная реализация исполняемой среды для языка Ruby, наряду с официальной MRI, JRuby и другими, менее известными разработками.
Релиз 2.0 считается совместимым с еще не вышедшей спецификацией Ruby 2.1, и будет в дальнейшем видоизменяться новыми версиями по мере закрепления новой функциональности в MRI. Ruby движется вперед, и все его пользователи должны следовать за ним. Именно к этому призывает главный человек в мире Ruby — Matz. Если вы все еще на 1.9 — как можно скорее переходите на 2.0, разработчики Ruby очень старались сделать переход на нее минимально трудоемким и болезненным. Цель проекта Rubinius также состоит в технологическом совершенствовании интерпретатора что позволило бы создавать более быстрые, стабильные и эффективно использующие компьютерные мощности приложения и сервисы. Ранее проект был известен скрупулезностью в отношении реализации всех аспектов языка Ruby, но сейчас такой подход к разработке несовместим с новой концепцией развития. Начиная с версии 2.0 команда Rubinius сконцентрируется на параллельных и распределенных вычислениях. Из-за этого не всякий существующий код будет работать на Rubinius, который пытается сделать из Ruby конкурента Go, Erlang, Clojure, Scala и Node.
Также, начиная с версии 2.0 изменяется цикл и нумерация релизов проекта. Ожидается, что новые версии будет выходить раз в неделю или около того. Как и ранее, ветка «мастер» будет содержать максимально стабильный код. Если при этом новый релиз окажется минорным, корректирующим ошибки, то номер его версии увеличится на единицу в третьей позиции (X.Y.Z -> X.Y.Z+1), а если изменение связано с новой функциональностью — то во второй (X.Y.Z -> X.Y+1.0). Это связано с тем, что как такового финального релиза все равно не будет, это не тот продукт. Всегда будут возникать баги, что-то добавляться в библиотеки или ядро, и работы у команды всегда будет довольно много. К версии 3.0 проект планирует перейти на семантическую нумерацию, а пока в течение 2-ой ветки будет делаться все для обеспечения безболезненности перехода.
Кроме того сейчас запущен подсайт http://releases.rubini.us, который будет хранить тарболлы с релизами и предоставлять к ним доступ через API. В течение нескольких дней все инсталяторы Ruby (RVM, rbenv и другие) должны перейти на работу именно с этим API.
Компоненты Rubinius
Многие слышали, что Rubinius — это еще одна реализация языка программирования Ruby. Однако это определение скрывает в себе множество деталей. Сейчас мы кратко рассмотрим используемые в Rubinius технологии и планах по их совершенствованию.
Архитектура Rubinius стандартна среди современных исполняемых сред для различных языков программирования.
Виртуальная машина исполняет байт-код, генерируемый компилятором Ruby. Стоит отметить, что каждый метод в Ruby имеет собственного интерпретатора. Это позволяет реализовать многие полезные вещи, например, встроенный отладчик. Только один из методов Ruby с определенными точками останова использует интерпретатор «debug».
Обобщенный сборщик мусора — довольно быстрый, обычно для при сборке он останавливает исполнение менее, чем не 15 мс. Приложения, запускаемые в Rubinius обычно работают с еще более короткими и редкими задержками, так как всю кучу надо очищать довольно редко. Также Rubinius использует частично параллельный способ отметки удаляемых объектов, что в дальнейшем и сокращает временные задержки при полной очистке.
Rubinius работает с настоящими системными потоками и не имеет глобальной блокировки интерпретатора (global interpreter lock, GIL). На многопроцессорных и многоядерных машинах код Ruby исполняется параллельно.
Динамический (JIT) компилятор Rubinius преобразует байткод Ruby в машинные коды. Поток, в котором работает JIT-компилятор, существует практически не зависимо от других потоков Ruby, поэтому его работа не воздействует не производительность приложения. JIT компилятор в реальном времени отслеживает наиболее часто вызываемые методы и используемые типы объектов и используя эту информацию он умеет совмещать методы приложения и стандартной библиотеки, генерируя хорошо оптимизированный машинный код, исполняемый в разы быстрее, чем это делает интерпретатор Ruby-байткода.
Стандартные библиотеки Rubinius (например, Array, Hash, Range ...), а также все вспомогательные инструменты (компилятор байткода и т.д.), написаны на Ruby, и Rubinius расценивает их как код стороннего Ruby-приложения. Такой подход заметно облегчает понимание и анализ всей системы инструментов Rubinius.
Планы на будущее
Наши планы — очень больная тема, ведь прогнозирование будущего остается неточной наукой. Но на основе цели по концентрации усилий вокруг параллельных и распределенных вычислений можно выделить следующие приоритетные направления работы:
1. В Rubinius нет глобальной блокировки интерпретатора, но нам еще есть куда улучшать управление параллельными потоками в системе. Во течение определенных фаз сборки мусора, определенных JIT-операций, fork/exec нам все равно приходится останавливать все потоки. Здесь еще нужно поработать и упростить имеющиеся проблемы.
2. Вместо GIL в Rubinius происходят локальные блокировки в различных местах. Их также стоит уменьшить, повысить эффективность работы на многоядерных процессорах, например, путем использования современных неблокирующих параллельных структур данных.
3. Сборщик мусора справляется довольно быстро и редко останавливает процесс, однако и над ним нам предстоит потрудиться.
4. JIT-компилятор уже ускоряет код Ruby в 2-4 раза по сравнению с исполнением байктода, но мы знаем, что можем лучше, постараемся улучшить понимание семантики языка с целью избежать необязательные выделения памяти и учет объектов, что негативно сказывается на производительности. Сам JIT-инструментарий будет видоизменен для повышения скорости разработки и тестирования новых идей по оптимизации Ruby.
Gem-ы в качестве компонентов
Возможность создания системы из компонентов означает управление довольной сложной структурой. Но в Ruby мы привыкли пакетировать и распространять компоненты в виде gem-пакетов.
Rubinius хочет привнести в разработку Ruby преимущества использования непрерывной интеграции, и в этом мы хотим широко использовать инфраструктуру gem-пакетов. Их использование сильно упростило сам Rubinius — все его главные компоненты стали независимыми gem-пакетами. Их стало просто и быстро обновлять по одиночке. Кроме этого, вся стандартная библиотека Rubinius также была преобразована в gem-пакеты. Это была тяжелая работа, ведь стандартная библиотека была самым старым кодом в Ruby.
Итак, распределенность и параллельность — это не будущее, а настоящее. Они крайне важны для успеха вашего сервиса. Из-за этого многие молодые и талантливые разработчики покинули Ruby и ушли в Erlang, Go, Clojure или Node. Но Ruby — прекрасный язык, и Rubinius создан для предоставления разработчикам высококлассных инструментов и технологий, позволяющих Ruby быть сильным конкурентом другим языкам. Если вам нравится писать на Ruby, то вам теперь не нужно искать более производительную альтернативу из-за каких-то технических ограничений. Давайте строить будущее вместе!
Автор: siomi