Ruby 2.6: podgląd JIT i nieskończone zakresy
Ruby 2.6.0 ukazuje się w Boże Narodzenie z pierwszym krokiem ku kompilatorowi JIT — dużą sprawą dla przyszłości Ruby — plus nieskończone zakresy, then jako alias dla yield_self i Bundler w bibliotece standardowej. Praktyczny przegląd.
Ruby 2.6.0 przybyło w Boże Narodzenie, a choć codzienne dodatki są przyjemne jak zwykle, nagłówek jest strategicznie znaczący: Ruby dostaje swój pierwszy kompilator JIT, jako eksperymentalny podgląd. To jeszcze nie powód do aktualizacji sam w sobie, ale pierwszy widoczny krok wieloletniego wysiłku, by uczynić Ruby znacząco szybszym — fundament słynnego celu „Ruby 3x3”. Oto przegląd, z nagłówkiem o tym, co to znaczy dla przyszłości języka.
MJIT: pierwszy krok ku szybszemu Ruby
Wielką wiadomością jest MJIT, pierwszy kompilator just-in-time Ruby, przybywający jako eksperymentalny, opt-in podgląd. JIT kompiluje często uruchamiany kod do natywnego kodu maszyny w czasie działania i jest centralną techniką stojącą za uczynieniem języków interpretowanych szybkimi. Podejście Ruby jest nietypowe i pragmatyczne: MJIT zapisuje kod C na dysk i używa systemowego kompilatora C, by skompilować gorące metody w biblioteki współdzielone, które VM potem ładuje.
ruby --jit my_program.rb # zgłoś się do JIT
Uczciwa ocena dla 2.6: MJIT nie jest jeszcze wygraną dla typowych aplikacji Rails. Obecnie pomaga obciążeniom związanym z CPU, ciężkim obliczeniowo, podczas gdy aplikacje Rails — zdominowane przez I/O, dyspozycję metod i alokację pamięci, a nie ciasne pętle numeryczne — widzą małą korzyść, a czasem regresję. Więc nie włączasz go na produkcji dziś. Jego znaczenie jest jako początek: to widoczny start ambicji „Ruby 3x3” (Ruby 3 będący trzy razy szybszy niż Ruby 2), a przez następnych kilka wydań to tu zostanie napisana historia wydajności Ruby. Warte bacznego obserwowania, nie wdrażania jeszcze.
Nieskończone zakresy
Mały, naprawdę przydatny dodatek składniowy: zakresy bez górnej granicy, (n..). Czytają się
naturalnie i porządkują częste wzorce:
# "wszystko od indeksu 2 w górę"
items[2..] # było items[2..-1]
# warunek bez końca w case
case score
when 90.. then "A"
when 70.. then "B"
else "C"
end
# scope'y / porównania czytane „n lub więcej”
ages.select { |a| (18..).cover?(a) }
array[2..] w znaczeniu „od indeksu 2 do końca” jest jaśniejsze niż lekko zagadkowe
array[2..-1], którego wszyscy się nauczyli, a nieskończone zakresy błyszczą w case/when dla
„ten próg lub powyżej”. Drobna funkcja, którą przyjmiesz bez zastanawiania się.
then: czytelna nazwa dla yield_self
Ruby 2.5 wprowadziło yield_self — metodę przypominającą pipe, która podaje odbiorcę do bloku —
ale jej nazwa była toporna. 2.6 dodaje then jako alias, i czyta się znacznie lepiej:
# ten sam potok wartości, teraz czytelny
config
.then { |c| build_url(c) }
.then { |u| fetch(u) }
.then { |r| parse(r) }
Ta sama zdolność, znacznie ładniejsza nazwa. then czyni potok „weź tę wartość, potem zrób to,
potem to” czytanym jak po angielsku, i to forma, po którą będziesz sięgać zamiast yield_self od
teraz.
Dodatki do kolekcji i Enumerable
Użyteczna porcja metod do pracy z kolekcjami:
Array#union,#difference,#intersectiondają nazwane, czytelne alternatywy dla symbolicznych operatorów zbiorów (|,-,&) i, w przeciwieństwie do operatorów, przyjmują wiele argumentów:a.union(b, c).Enumerable#chainleniwie konkatenuje enumerable w jeden bez budowania pośredniej tablicy —(1..3).chain([4, 5]).each { ... }— przydatne do iterowania kilku kolekcji jako jednej.Enumerable#filterprzybywa jako alias dlaselect, dopasowując nazewnictwo Ruby do terminu, którego używa większość innych języków.
Żaden nie jest głęboki, ale każdy zastępuje mały idiom jaśniejszą metodą.
Bundler w bibliotece standardowej
Po cichu znacząca zmiana dla ekosystemu: Bundler jest teraz dołączony do Ruby jako część biblioteki standardowej. Bundler był uniwersalnym menedżerem zależności od lat, ale był osobnym gemem, który instalowałeś; uczynienie go częścią samego Ruby uznaje tę rzeczywistość i wygładza konfigurację — świeża instalacja Ruby przychodzi teraz z narzędziami zależności, których używa każdy projekt, bez dodatkowego kroku. Małe, ale usuwa drzazgę z onboardingu i CI.
Mniejsze dodatki
Dopełniając wydanie: Kernel#then jak omówiono; Proc#call i przekazywanie bloków robią się
szybsze (kontynuując stałą pracę nad wydajnością); przypisanie stałej można uczynić
podnoszącym błąd przy redefinicji, pomagając łapać przypadkowe nadpisanie stałych; i zwykła runda
udoskonaleń biblioteki standardowej oraz deprecjacji. Niedramatyczne porządki trwają.
Czy aktualizować?
Tak dla funkcji języka, bez pośpiechu dla JIT. Codzienne dodatki — nieskończone zakresy, then,
metody kolekcji, Bundler w stdlib — są przyjemne, addytywne i bez ryzyka, więc przyjmujesz je
naturalnie. JIT to ten nie do wdrażania jeszcze: to eksperymentalny podgląd, który nie pomaga (a
może szkodzić) typowym obciążeniom Rails w 2.6, więc zostaw go wyłączonym na produkcji na razie.
Ale zrozum jego znaczenie — to otwierające posunięcie wieloletniego pchnięcia Ruby ku byciu
dramatycznie szybszym, cel „3x3” uczyniony widocznym. Aktualizuj dla ergonomii dziś i obserwuj, jak
JIT dojrzewa przez następne wydania, bo to tam za chwilę rozwinie się ciekawa historia wydajności.
Charakterystycznie praktyczne wydanie gwiazdkowe, z strategicznie ważnym ziarnem zasianym w
środku.