SmallRuby: nová implementace Ruby z ČVUT, napsaná ve Smalltalku

Jak známo, Ruby patří k jazykům, které mají poměrně hodně implementací. Jejich seznam se přibližně před rokem a půl stabilizoval a najdete ho třeba v mé diplomce (sekce 2.5). Bylo proto pro mě velkým překvapením, když jsem objevil implementaci novou – SmallRuby. Ještě větší překvapení následovalo, když jsem zjistil, že pochází z ČVUT.

Co je SmallRuby?

SmallRuby je implementace Ruby v prostředí Smalltalk/X. Její základ vznikl jako diplomová práce Jana Karpíška, studenta ČVUT. Podle projektového webu a podcastu jde ale o týmový projekt pod vedením Jana Vraného.

Hlavní motivací pro vznik SmallRuby byl nízký výkon původní implementace Ruby (MRI). To je dlouho známý problém (i když aktuální verze Ruby 1.9 ho alespoň částečně řeší). SmallRuby výkon zvyšuje překladem kódu v Ruby do bajtkódu smalltalkového virtuálního stroje. Ten je pak spouštěn a optimalizován stejným způsobem, jako kdyby byl původní kód napsán přímo ve Smalltalku – a běží tedy ve výsledku poměrně rychle.

Idea SmallRuby je velmi podobná projektu MagLev, který dělá v podstatě totéž, ale s jiným smalltalkovým virtuálním strojem, a navíc přidává podporu distribuovaného stavu a výpočtů. SmallRuby se snaží využít prostředí Smalltalku jiným způsobem a například přidává integraci Ruby do jeho vývojového prostředí:

Ruby a smalltalkové nástroje
Ruby a smalltalkové nástroje. Převzato z webu SmallRuby.

Přirozené spojení

Využití Smalltalku pro implementaci Ruby je poměrně přirozené, protože oba jazyky jsou si poměrně podobné (oba jsou čistě objektové a používají třídy a dědičnost). Ruby je ale o něco dynamičtější, což při implementaci SmallRuby podle autorů způsobilo nemalé problémy. Některé jeho vlastnosti nebyly kvůli nekompatibilitě jazyků zatím implementovány vůbec.

Pokud vás zajímají detaily (mě zajímaly moc :-), doporučuji si přečíst přímo zmiňovanou diplomovou práci. Je sice místy obtížně srozumitelná a sloh zřejmě není autorovou silnou stránkou, nicméně to podstatné z ní lze pochopit bez větších problémů.

Výkon

Pokud byl motivací SmallRuby výkon, je na místě se ptát, zda se projektu opravdu podařilo Ruby zrychlit. Odpověď je ano. Autoři se na webu chlubí grafem, který ukazuje rychlost běhu některých standardních rychlostních testů, které obsahuje přímo původní implementace Ruby:

Graf srovnávající SmallRuby a vybrané další implementace Ruby
Graf srovnávající SmallRuby a vybrané další implementace Ruby. Převzato z webu SmallRuby.

Jak je vidět, SmallRuby je podstatně rychlejší než Ruby 1.8, a to až 40×. Podobně je tomu s JRuby. Ruby 1.9 předežene až na dva testy spolehlivě také. Zajímavé by bylo ještě srovnání s dalšími implementacemi a také s novější verzí JRuby (verze v grafu je přibližně rok stará).

Nutno dodat, že nejsou spouštěny zdaleka všechny testy ze sady, protože v některých se vyskytují konstrukce, které SmallRuby v tuto chvíli nepodporuje.

Závěr

SmallRuby je rozhodně zajímavý projekt – pro nás o to víc, že pochází z českých luhů a hájů. V současné době ale podporuje jen malou podmnožinu jazyka Ruby – autoři se zatím téměř vůbec nezabývali jeho běhovou knihovnou a vynechali i některé jazykové konstrukce. Pokud mají v SmallRuby jít spustit reálné programy, je potřeba na těchto oblastech zapracovat.

I pokud by SmallRuby podporovalo dostatečně velkou podmnožinu jazyka Ruby, je otázka, zda má reálné praktické využití. Dovedu si totiž jen obtížně představit, že si někdo bude například na server instalovat smalltalkový virtuální stroj jen kvůli tomu, aby zvýšil výkon implementace Ruby – zvlášť pokud Smalltalk nezná. Na druhou stranu není až tak nereálná třeba varianta, že se Ruby časem stane skriptovacím jazykem pro Smalltalk/X podobně, jako se Groovy, JRuby a další staly skriptovacími jazyky pro Javu/JVM.

Autorům s projektem každopádně přeji mnoho zdaru – sám moc dobře vím, jak je těžké alespoň trochu použitelnou implementaci Ruby vytvořit a kolik práce ještě mají před sebou, pokud SmallRuby chtějí dotáhnout k reálné použitelnosti.

Dec 4, 2009 – 9:32

Comments

optik
Moc pěkné. K těm grafům - myslel jsem, že Ruby 1.9 na tom tedy bude lépe než JRuby. Čím si to vysvětlujete? To je ten yarv takový louda, nebo to vývojáři JRuby pěkně nakoply? Není to tak dávno, co bylo JRuby pomalejší než 1.8. Nebo nějaká změna v JVM?
David Majda
[1] Vím jen to, že JRuby se v posledních dvou letech hodně vyvíjelo a optimalizace výkonu měla poměrně vysokou prioritu. U YARVu mě kdysi trochu překvapilo, že nezrychlil Ruby zas až tak moc, ale o důvodech bych tu mohl jen spekulovat - nikdy jsem ho podrobněji nezkoumal.

Obecně ale není překvapivé, že interpret jazyka využívající JVM je rychlejší než interpret využívající vlastní virtuální stroj na bázi bajtkódu. JVM je totiž hodně otimalizovaný a hlavně si bajtkód může kompilovat přímo do nativního kódu.
Miloslav Ponkrác
To, že YARV moc nezrychluje by mě ani nepřekvapilo. Udělat dobrý virtuální stroj s rychlým během je něco co chce mnoho let práce, velmi chytré mozky (jedny z nejlepších) a velmi promakaný JIT a pak velkou sumu peněz na vývoj. Je jen velmi nepravděpodobné, že YARV měl všechny tyto podmínky.

JVM se vyvíjí už kolik let a stále se implementují další a další optimalizace a nápady na všech frontách od samotné implementace běhu byte kódu přes optimalizace garbage collectoru a x dalších věcí.

Realita bude taková, že jakýkoli amatérský virtuální stroj bude zaostávat za jakýmkoli opravdu profesionálním a dobře financovaným projektem.

Prostě určité projekty jsou už takové složitosti, že potřebují profesionální řízení a v podstatě komerční přístup. Třeba udělat kvalitně optimalizující kompilátor (což ani zdaleka není gcc), nebo kvalitní rychlý virtuální stroj jsou složité projekty, které se nedají dělat na koleně. A chtějí velmi kvalitní, znalé a zkušené lidi a mnoho času.

Pavel Křivánek
Pavel Křivánek
Na SmallRuby jsem se před nějakou dobou díval. Hlavní výhodu tohoto projektu bych viděl v tom, že Ruby tak získá podporu image a smalltalkovského vývojového prostředí. Ale tím, že z Ruby podporuje v podstatě jen vlastnosti, které je možné přímo přepsat do Smalltalku, na mě bohužel působil spíše rozpačitě.
David Majda
[4] Ano, ten přímý přepis je dost omezující a budou od toho muset na mnoha místech upustit, pokud chtějí být kompatibilní s celým nebo téměř celým Ruby. Možná cesta je buď některé věci emulovat, nebo upravit VM, aby podporoval potřebné vlasnosti.
Jan Vrany
Jan Vrany
Nevim, co myslite tim primym prepisem... Slaba podpora konstrukci Ruby je v dnesni dobe dana hlavne nedokonalym parserem - parsoba Ruby neni snadne. 80% casu z celeho vyvoje SmallRuby jsme hackovali parser - bohuzel. Mame par myslenek, jak na parsovani vyzrat, jen mit cas :-)

Samozrejme, zmenu ve VM jsou v planu, nicmene to je pomerne komplikovana vec. Navic to chceme udelat poradne, coz veci jeste komplikuje. Zda se nevyhnutelne implementovat "selector namespaces" a nejakou formu metaobject protocolu na modifikaci lookupu metod...



David Majda
[6] Já si pod přímým přepisem v komentáři [4] představil to, že jsou prakticky všude využívány mechanismy Smalltalku a prakticky nic není emulováno, což vede k nejrůznějším omezením. Příklady:

1. Základní třídy Ruby jako String, Array, TrueClass apod. jsou namapovány na analogické třídy Smalltalku a nikoliv na zvláštní třídy jen pro Ruby, na původních třídách Smalltalku nezávislé. Druhý způsob je obvyklejší u implementací jako JRuby nebo IronRuby.

2. Volání metod je zajišťováno přímo Smalltalkem, což jak jsem pochopil z diplomky omezuje například podporu metod s proměnlivým počtem parametrů.

3. Instanční proměnné objektů v Ruby jsou ukládány přímo jako instanční proměnné objektů ve Smalltalku, což vyžaduje rekompilace. V MRI a dalšéch implementacích je použita hash tabulka.
Jan Vrany
Jan Vrany
Ano, SmallRuby se snazi vsude vyuzivat mechanismy VM, ktery je celkem sity na miru Smalltalku. Nicmene v soucasne dobe nas to az zas tak neomezuje:

1) Ano, pouzivame Smalltalk tridy, krom SmallInteger (aka FixNum)
to delat nemusime, a muzeme vybudovat kompletni paralelni hierarchii Ruby trid. To ale nechceme, nebot interoperabilita obou
jazyku je jednim z dulezitych cilu. Jediny problem, ktery toto reseni prinase je problem name clashes, kterych ale neni moc, co jsme zatim meli moznost zjistit.

2) Neomezuje, jen se musi pouzit par triku. Soucasna verze podporuje jak nepovinne argumenty tak promenny pocet argumentu.
Pouzivame k tomu tzv. "synthetic methods".

3) Ano, vyzaduje to rekompilaci, to ale dme meho nazoru neni
velky problem. Smalltalk stoji a pada na inkrementalni kompilaci metod, takze to VM celkem slusne zvlada. Navic vetsine beznych rekompilaci se da vyhnout o neco chytrejsim prekladacem - podle me to ale nema z vykonostniho hlediska smysl. Pouziti hash tabulky je mozne, ale z vykonoveho hlediska to neni moc sikovne.

Nase reseni ma jediny problem, totiz moznost pridani object-specific metody ktera definuje vlastni instanci promennou.
To lze vyresit jen operaci #become: ktera je casove vemi narocna. Samozrejme, pokud tohle bude vykonostni problem, neni
problem pouzit hybridni techniku - cas v inst. promennych, cast v hash tabulce. V zasade neni ani problem pouzit jak hash tabulku tak become a nechat na programatorovi, ktery pristup ma kdy pouzit...pripadne pouzit become jako default a na zaklade statistyckych dat posleze pro danou tridu pouzit hybridni techniku. Moznosti jak to resit jsou mraky...


David Majda
Díky za vysvětlení.

Ad 1: Myslím, že vámi zvolený přístup začne způsobovat problémy s kompatibilitou s Ruby hlavně ve chvili, kdy začnete implementovat reflection a další dynamičtější věci. Neříkám, že budou neřešitelné, ale mám pocit, že tady jste si trochu zkomplikovali práci do budoucna.

Add comment

It is not possible to add comments to posts older than one month.