Wiele interpreterów i środowisk wykonawczych języka programowania Ruby

Opublikowany: 2022-03-11

Wstęp

Tak jak istnieje wiele odcieni rubinowego klejnotu, istnieje wiele implementacji interpretera Ruby.

Najczęściej używanym interpreterem Ruby jest implementacja referencyjna, Ruby MRI, opracowana w C przez twórcę Rubiego (Yukihiro Matsumoto) i główny zespół Ruby.

Nasz przewodnik rekrutacyjny Ruby on Rails wspomina, że ​​niektóre wady Railsów można potencjalnie rozwiązać lub uniknąć, używając alternatywnego interpretera Ruby. W tym artykule przedstawiono różne dostępne obecnie implementacje i środowiska wykonawcze interpretera Ruby, omawiając zalety i wady każdego z nich.

Lista interpreterów i środowisk wykonawczych Ruby, w tym mruby, JRuby, RubyMotion, Rubinius i Ruby MRI

Historia wersji Rubiego (i jak wpływa na alternatywne implementacje)

Niestety, nie ma odpowiednika Python Language Reference dla Ruby (ISO/IEC 30170:2012 opisuje Ruby 1.8 / Ruby 1.9, ale nie istnieje odpowiednia specyfikacja dla Ruby 2.x). W przypadku braku takiej specyfikacji języka, implementatorzy Ruby zazwyczaj polegają na opartej na społeczności RubySpec, która określa oczekiwane zachowanie języka Ruby poprzez testy, które można uruchomić w dowolnym interpreterze Ruby. RubySpec jest zatem używany przez implementatorów Ruby do weryfikacji zgodności behawioralnej ich implementacji Ruby ze standardem de facto.

Z powodu braku formalnej specyfikacji, nowe wydania Rubiego często po prostu odpowiadają nowym wydaniom Ruby MRI. Warto zauważyć, że istnieje otwarte zagadnienie, które omawia proces projektowania w celu oddzielenia Ruby (języka) od Ruby MRI.

Jednak biorąc pod uwagę obecne ścisłe powiązanie między językiem Ruby a implementacją referencyjną MRI, twórcy alternatywnych implementacji Ruby czasami mają trudności z nadążaniem za zmianami językowymi wprowadzanymi w każdym nowym wydaniu MRI.

Nigdy nie było to trudniejsze niż w przejściu między Ruby 1.8 i Ruby 1.9. W 2007 roku, starając się uporządkować i skonsolidować składnię Rubiego (jako język ewoluował w ciągu dekady od wydania Rubiego 1.0), główny zespół Ruby wydał Ruby 1.9.0, wersję, która wprowadziła do języka wiele niezgodności wstecznych . W rezultacie nie wszystkie implementacje Rubiego zainwestowały wysiłek niezbędny do wykonania skoku składniowego z 1.8 do 1.9. W związku z tym istnieje kilka implementacji Rubiego opartych na 1.8, które nie są już używane przez społeczność, ale które nadal możesz znaleźć w Internecie lub o których mówią stare osoby z Ruby.

Nowa wersja Ruby MRI jest wydawana w każde Boże Narodzenie, zgodnie z zasadą semantycznego wersjonowania. Ruby 2.0 (wydany 2013) i 2.1 (wydany 2014) wprowadziły dodatkowe funkcje językowe, z których mogą skorzystać programiści Ruby, bez utraty kompatybilności wstecznej z Ruby 1.9.

Dlaczego warto korzystać z alternatywnej implementacji Rubiego? Co jest nie tak z MRI?

Istnieje wiele alternatywnych implementacji Rubiego, obsługujących szeroką gamę przypadków użycia i środowisk. Środowiska Java Enterprise. Aplikacje mobilne. Implementacje JavaScript. Maszyny z niskim procesorem/RAM. Oprócz obsługi tych przypadków użycia alternatywne implementacje mogą czasami oferować dodatkowe zwiększenie szybkości lub bardziej efektywne wykorzystanie pamięci, w zależności od cech aplikacji.

Przez długi czas wielu programistów Ruby on Rails używało Ruby Enterprise Edition (REE) zamiast MRI, korzystając z lepszych technik zarządzania pamięcią w REE w porównaniu z ówczesną wersją MRI. (REE zostało później przerwane, ale w 2012 r.)

Chociaż MRI jest domyślną implementacją Rubiego, niekoniecznie jest to właściwy wybór dla wszystkich środowisk i scenariuszy. Na przykład obsługa współbieżności MRI jest gorsza od obsługi JRuby lub Rubinius. Ponadto, chociaż systemy pamięci i zbierania śmieci MRI stale się poprawiają, nadal mają pewne problemy.

Poniższa ankieta dotycząca implementacji Rubiego ma na celu pomóc w wyborze interpretera najlepiej dopasowanego do celów operacyjnych i ograniczeń projektu.

Rubinowy tłumacz Matza (MRI) / CRuby

Napisany w C przez główny zespół Ruby kierowany przez Yukihiro Matsumoto („Matz”, twórca Rubiego), MRI jest referencyjną implementacją Ruby, która służy jako de facto standard. Jeśli dostawca systemu operacyjnego zawiera na przykład wersję Ruby jako część zainstalowanego oprogramowania systemu operacyjnego, zwykle jest to wersja MRI. MRI korzysta z większej liczby opłacanych członków podstawowego zespołu niż jakakolwiek inna implementacja Ruby, a także z zasobów dedykowanych od osób lub firm, które chcą ulepszyć ekosystem Ruby.

Nowa wersja Ruby MRI – często wprowadzająca nowe funkcje językowe, oprócz standardowych zmian w bibliotekach – jest wydawana w każde Boże Narodzenie. Funkcje są najpierw implementowane w Ruby MRI, zwykle w oparciu o dyskusje na liście dyskusyjnej deweloperów Ruby. Inne implementacje Rubiego pozostają w tyle, w niektórych przypadkach nawet o lata.

JRuby

JRuby to wersja Ruby zaimplementowana na wierzchu wirtualnej maszyny Java (JVM). Ponieważ coraz popularniejsze staje się uruchamianie na maszynie JVM języków innych niż Java (patrzę w twoim kierunku, Clojure i Scala), implementacja Ruby oparta na JVM prawdopodobnie zyska na popularności.

Ruby w JVM oznacza również, że Ruby może działać wszędzie tam, gdzie może działać Java (jak telefony z Androidem, na przykład używając Ruboto). Dodatkowo, dzięki interoperacyjności JVM, kod JRuby może korzystać z platformy Java, obejmującej zarówno biblioteki standardowe, jak i zewnętrzne.

JRuby przydaje się również do przeniesienia rozwiązania opartego na Rails do środowiska wdrażania opartego tylko na Javie, spakowania aplikacji Rails jako pliku .war do wdrożenia w kontenerze Tomcat lub jako aplet Java działający jako część interfejsu internetowego , na przykład.

Jednak dla tych, którzy nie są przyzwyczajeni do JVM, JRuby oferuje standardowe problemy związane z JVM, takie jak powolne uruchamianie interpretera Ruby, debugowanie problemów z CLASSPATH, jeśli używasz bibliotek Java innych firm, większe zużycie pamięci i fakt, że teraz twój kod musi być napisany z uwzględnieniem kwestii bezpieczeństwa wątków.

Ponadto niektóre funkcje Rubiego (interfejsy C API i jedno z potężnych narzędzi Ruby do introspekcji, moduł ObjectSpace) nie są zaimplementowane w JRuby.

Mimo wszystko zalety korzystania z JVM mogą przeważać nad wadami w pewnych sytuacjach lub projektach. JVM pozwala na wiele optymalizacji wydajności, takich jak włączanie kompilatora JIT lub używanie natywnych obiektów Java i interfejsów API.

Jako przykład przekonującego przypadku użycia JRuby, mój były współpracownik miał kiedyś problem obciążający procesor, który początkowo rozwiązał za pomocą wątków w Ruby 1.9.3. Kiedy przeszedł na JRuby i użył java.util.concurrent.Executors , zauważył poprawę wydajności o wiele rzędów wielkości (dziesiątki tysięcy razy szybszą) dla tej operacji. Zobacz jego eksperyment tutaj.

Rubinius

Rubinius to implementacja Rubiego, która implementuje ogólne środowisko wykonawcze dla języków dynamicznych na maszynie wirtualnej niskiego poziomu (LLVM). Korzystając z tej infrastruktury i technologii kompilatora JIT, Rubinius może często uruchamiać kod Ruby z mniejszym obciążeniem niż MRI.

Rubinius jest również zbudowany przy użyciu jak największej ilości Rubiego, aby przyspieszyć i ułatwić rozwój interpretera / środowiska wykonawczego.

Ciekawostka: RubySpec początkowo powstał w trakcie wdrażania Rubiniusa.

Podobnie jak JRuby, Rubinius zawiera kompilator JIT, lepsze zarządzanie pamięcią i bardziej dojrzałą maszynę wirtualną niż Ruby MRI. Jednak w przeciwieństwie do JRuby, Rubinius obsługuje biblioteki Ruby C, a podstawy Rubinius są napisane w C++, a nie w Javie.

Rubinius może być dobrym rozwiązaniem, gdy potrzebujesz wysokiej wydajności na swoich serwerach Rails, bez konieczności uczenia się lub innych wad JRuby.

mruby

mruby ma być osadzoną wersją Rubiego (obsługującą Ruby 1.9.3). Dzięki mruby możesz zaoferować Ruby jako język skryptów / automatyzacji w natywnych aplikacjach, używać go do skryptowania gier, a nawet do programowania płytek mikrokontrolerowych, takich jak Raspberry Pi.

Jeśli Twoja platforma ma poważne ograniczenia zasobów, mruby może być właśnie dla Ciebie interpreterem Rubiego. mruby jest również używany do:

  • Twórz aplikacje na iOS (jako konkurent RubyMotion, omówione poniżej)
  • Osadź Rubiego w aplikacjach na iOS, aby przyspieszyć rozwój
  • Zaoferuj użytkownikom końcowym wbudowany język skryptowy do celów automatyzacji

W miarę jak Internet rzeczy staje się coraz bardziej rzeczywistością, automatyka domowa staje się coraz bardziej popularna, a niezwykle przenośne (i stosunkowo wydajne) komputery stają się coraz bardziej powszechne, krajobraz wspieranych platform docelowych staje się coraz bardziej zróżnicowany. mruby pomaga zrobić to w tym samym produktywnym języku, którego używa się na pulpicie.

Opal

Opal to transpiler do przekształcenia Rubiego w JavaScript.

Wraz z pojawieniem się Coffeescript programiści dowiadują się, że nie muszą wpisywać JavaScript, aby uzyskać JavaScript. Chociaż Coffeescript ma swoje zalety, używaj go wystarczająco długo, a na pewno natkniesz się na rzeczy, których nie lubisz w języku.

Wpisz Opal: wpisz Ruby, pobierz JavaScript . Całkiem fajne.

Opal stara się być jak najbardziej spójny z innymi implementacjami Ruby i dlatego jest również testowany pod kątem podzbioru RubySpec. Istnieją jednak pewne niezgodności, wynikające z natury środowisk wykonawczych JavaScript i JavaScript. Na przykład ciągi i symbole w Opal są równe, a Opal nie zapewnia żadnych mechanizmów wątków ani wykonywania powłoki.

Opal działa samodzielnie lub może być używany jako część potoku zasobów Rails (np. do automatycznej somefile.js.rb pliku somefile.js.rb do JavaScript).

Być może masz problematyczną domenę dobrze pasującą do asynchronicznego wzorca współbieżności JavaScript (np. małą usługę Node.js), ale potrzebujesz języka lub pewnych klejnotów z przestrzeni Ruby. Opal może być dla Ciebie dobrym rozwiązaniem w takim przypadku.

A może chcesz napisać pełną aplikację internetową Ruby. Z Opalem możesz. Miej jeden interpreter Ruby uruchamiający kod Ruby po stronie serwera, a następnie pozwól Opalowi generować JavaScript do uruchomienia po stronie klienta.

Opal zdaje sobie sprawę, że prawdopodobnie będziesz wchodzić w interakcje z innymi interfejsami API JavaScript (na przykład DOM lub Node.js). W związku z tym ułatwia przejście do JavaScript i zapewnia trochę cukru syntaktycznego Ruby w stosunku do popularnych bibliotek JavaScript, takich jak jQuery.

Jednak skoncentrowana na JavaScript natura Opal jest zarówno jego siłą, jak i słabością. Z drugiej strony, środowisko uruchomieniowe Opala to środowisko uruchomieniowe JavaScript, a Opal jest informowany o decyzjach projektowych JavaScript. Więc jeśli szukasz dobrej implementacji Rubiego do napisania małego skryptu powłoki lub szukasz lepszego środowiska wykonawczego Ruby dla swojej aplikacji Railsowej, Opal prawdopodobnie nie jest najlepszym wyborem.

RubyMotion

RubyMotion jest zarówno (a) implementacją Ruby (napisaną przy użyciu Objective-C i Cocoa), jak i (b) zestawem powiązań językowych, dzięki czemu programiści mogą uzyskać dostęp do interfejsów API Cocoa za pośrednictwem Ruby.

RubyMotion to komercyjny produkt, który umożliwia pisanie natywnych aplikacji Cocoa w Ruby. RubyMotion 2.0 umożliwia pisanie aplikacji na iOS i Mac OS X w Ruby, a RubyMotion 3 obiecuje zapewnić to samo wsparcie dla Androida.

RubyMotion implementuje wersję 1.9 języka Ruby.

Nieistniejące wdrożenia

Przez lata od wprowadzenia Rubiego, niektóre implementacje Rubiego, które powstały, zostały porzucone lub przerwane, takie jak:

  • Ruby Enterprise Edition (REE). REE był rozwidleniem MRI 1.8 od ludzi z Phusion Passenger, który zaimplementował wiele ulepszeń pamięci i zbierania śmieci dla twórców stron internetowych. Przez kilka lat była to domyślna implementacja Ruby wdrażana w produkcyjnych witrynach Rails. Jednak nigdy nie został zaktualizowany dla Ruby 1.9 lub Ruby 2.0 i został ostatecznie wycofany w 2012 roku.
  • Żelazny Rubin. IronRuby to Ruby zaimplementowany na platformie Microsoft .NET, napisany w C#, a przez pewien czas projekt był finansowany przez Microsoft. Porzucone w 2011 roku, IronRuby ostatnio wspierało Rubiego 1.8.6.

Zakończyć

Istnieje wiele różnych środowisk wykonawczych i tłumaczy do wyboru w krajobrazie Ruby. W przypadku większości projektów Ruby, implementacja referencyjna Ruby (Ruby MRI) pozostaje preferowanym interpreterem. Jednak alternatywne implementacje Rubiego mogą być dobrym wyborem dla twojego projektu, w zależności od twoich funkcjonalnych i technicznych celów i ograniczeń.

Jako referencyjna implementacja Rubiego, MRI szybciej uzyskuje nowe funkcje językowe, ma wystarczająco dobrą współbieżność i historie pamięci (które są tylko coraz lepsze) i ma najszerszą kompatybilność z klejnotami (niektóre częściowo napisane w C). Podsumowując, MRI jest solidnym, niezawodnym wyborem do ogólnego zastosowania kodu Ruby.

W przypadku większych wdrożeń w przedsiębiorstwach lub w sytuacjach, w których musisz wejść w interakcję z kodem Java (lub innymi językami JVM) albo potrzebujesz wysoce rozwiniętych wzorców współbieżności, JRuby jest atrakcyjną opcją.

I oczywiście, jeśli masz wyjątkowe potrzeby (np. pisanie JavaScript, uruchamianie na obecnej generacji urządzeń wbudowanych itd.), inne alternatywy dla Rubiego mogą być właśnie tym, czego szukasz.

Dzięki szerokiej gamie środowisk wykonawczych i interpreterów Ruby do wyboru, Ruby okazuje się być językiem elastycznym, przydatnym w szerokiej gamie środowisk komputerowych, począwszy od korporacyjnego sklepu z dużymi narzędziami Java, po oprogramowanie kontrolujące działanie światła w Twoim biurze podłączyłeś swoje Raspberry Pi do ostatniego weekendu. Wybór odpowiedniego narzędzia do właściwego celu jest niezbędny, tak, ale mam nadzieję, że ten artykuł pokazał ci, że Ruby to znacznie więcej niż domyślny interpreter Ruby, który jest dostarczany z twoim systemem operacyjnym.

Świat Ruby jest znacznie ulepszony dzięki alternatywnym zespołom implementacyjnym Ruby pracującym z głównym zespołem Ruby MRI, gdy proponowane są zmiany w języku. Dodają różnorodność do społeczności implementacji Ruby, dodając swoje ciężko zdobyte doświadczenia z implementacją Rubiego i własne spojrzenie na funkcje wprowadzane do języka. Entuzjaści Rubinów wspólnie mają wobec tych zespołów wielki dług wdzięczności. Brawo dla nich za ich wysiłki!