Cała oryginalna treść jest tworzona po ukraińsku. Nie wszystkie treści zostały jeszcze przetłumaczone. Niektóre posty mogą być dostępne tylko po ukraińsku.Dowiedz się więcej

Włączamy YJIT w Ruby 3.2.1 (Ruby on Rails)

Okładka posta: Włączamy YJIT w Ruby 3.2.1 (Ruby on Rails)
Ta treść została automatycznie przetłumaczona z ukraińskiego.
Na początku trzeba zrozumieć, czym jest JIT, YJIT i czy jest nam potrzebny. W tej notatce opiszę proces aktualizacji ruby (ponieważ YJIT jest instalowany razem z ruby tylko przy użyciu flagi). Przetestujemy szybkość Ruby i Ruby z YJIT.

Co to jest JIT i YJIT?

JIT (Just-In-Time) kompilacja w Ruby — to technologia, która przekształca bajt-kod Ruby w nattywny kod maszynowy bezpośrednio podczas wykonywania programu. Użycie JIT może znacznie zwiększyć wydajność wykonywania programu, ponieważ natywny kod maszynowy działa szybciej niż interpretowany bajt-kod. Ruby używa maszyny wirtualnej YARV (Yet Another Ruby VM), która przekształca napisany kod Ruby w bajt-kod przed jego wykonaniem. Dodanie JIT do tego procesu pozwala dynamicznie kompilować niektóre części kodu w locie, co przyspiesza działanie kodu i zmniejsza obciążenie serwera.
YJIT - to nowy kompilator JIT, który jest już wbudowany w Ruby od wersji 3.1. YJIT wykorzystuje tzw. "leniwe" JIT-kompilowanie, gdzie kompilacja jest wykonywana tylko dla "gorących" ścieżek wykonania, które są często używane. To zmniejsza koszty kompilacji kodu, który jest rzadko wykonywany, i zapewnia wzrost wydajności tam, gdzie jest to najbardziej potrzebne.
YJIT zwiększa szybkość wykonywania programów bez potrzeby wprowadzania istotnych zmian w samym kodzie. YJIT jest wynikiem próby optymalizacji działania Ruby za pomocą JIT-kompilacji, zachowując przy tym stabilność i zgodność z istniejącymi programami.

Sprawdzamy, czy YJIT jest włączony

Mój lokalny setup - macOS, rbenv i brew. Lokalnie sprawdzamy wersję ruby i czy YJIT jest włączony:
Terminal:
ruby -v

ruby 3.2.1
Konsola Rails:
irb(main):003:0> RubyVM::YJIT.enabled?
(irb):3:in `<main>': niezainicjowana stała RubyVM::YJIT (NameError)
                                                          
RubyVM::YJIT.enabled?                                     
      ^^^^^^
To znaczy, obecnie Ruby nie ma YJIT.

Mierzymy szybkość wykonywania Ruby bez YJIT

Stworzymy skrypt, który będzie liczył ciąg Fibonacciego. Trochę googlowałem i zapytałem ChatGPT, jak najlepiej zrobić prosty benchmarking i to jest najczęstsza opcja.
Tworzymy plik benchmark.rb z kodem:
require 'benchmark'

def fibonacci(n)
  return n if n <= 1
  fibonacci(n - 1) + fibonacci(n - 2)
end

puts Benchmark.measure {
  fibonacci(40)
}
Uruchamiamy:
ruby ~/Desktop/benchmark.rb
I mój wynik obecnie (bez YJIT):
 8.309469   0.000711  8.310180 (8.320920)

Instalujemy Ruby z YJIT

Obecnie mam ruby 3.2.1 (rbenv). Muszę zainstalować tę samą wersję, ale już z YJIT. Zaczynamy.
Disclaimer:
Każdy ma swój setup. Podany przykład to tylko mój przypadek.
Oficjalna dokumentacja mówi, że YJIT wymaga:
  • Kompilatora C, takiego jak GCC lub Clang
  • GNU Make i Autoconf
  • Kompilator Rust rustc i Cargo (jeśli chcesz budować w trybie dev/debug)
    • Wersja Rust musi być >= 1.58.0.
Z tego wszystkiego muszę tylko zainstalować Rust (Fajnie, prawda? Język programowania Rust jest używany jako kompilator).
Instalujemy Rust za pomocą brew:
brew install rust
To może zająć dość dużo czasu (~10min).
W .zshrc trzeba dodać następującą flagę:
export RUBY_CONFIGURE_OPTS="--enable-yjit"
Bez flagi Ruby zostanie zainstalowane bez YJIT (domyślnie jest wyłączony). To ważny punkt.
Restartujemy terminal, aby załadował RUBY_CONFIGURE_OPTS
Instalujemy Ruby (technicznie, rbenv install 3.2.1 będzie wykonywane z flagą --enable-yjit):
\W $ rbenv install 3.2.1
rbenv: /Users/user/.rbenv/versions/3.2.1 już istnieje
kontynuować instalację? (y/N) y
Po instalacji sprawdzamy, czy YJIT działa oraz benchmarki wykonania pliku benchmark.rb.
Jest tu pewien szczegół. YJIT, nawet jeśli jest zainstalowany razem z Ruby - jest wyłączony.
Dodaj tę flagę, aby ruby uruchamiał się z YJIT:
export RUBY_YJIT_ENABLE=true
Następnie powinniśmy zobaczyć +YJIT przy sprawdzaniu ruby -v
ruby -v
ruby 3.2.1 (2023-02-08 revision 31819e82c8) +YJIT [x86_64-darwin23]
irb
RubyVM::YJIT.enabled?
=> true

YJIT działa. Teraz testujemy.

ruby ~/Desktop/benchmark.rb
I otrzymujemy:
1.624351 0.000245 1.624596 (1.626251)
To znaczy, różnica w szybkości wykonywania skryptu wynosi 5,11 razy:
8.309469/1.624351=5,1155624616
Technicznie, to dość duża i znacząca aktualizacja w szybkości Ruby. Włączyłem tylko jedną opcję, na poziomie kompilacji uzyskujemy bardzo potężną optymalizację. YJIT jest już gotowy do produkcji i może być stosowany na serwerach produkcyjnych, na przykład dla aplikacji Ruby on Rails. Na przykład heroku oferuje włączenie YJIT za pomocą jednej komendy:
heroku config:set RUBYOPT="--enable-yjit"

Ten post nie ma jeszcze żadnych dodatków od autora.

27 kwi 09:29

Co to jest CC i BCC w e-mailach? Do czego i jak ich używać?

meme code
meme code@memecode
Czym jest prompt (prompt) i inżynieria promptów?
3 maj 12:08

Czym jest prompt (prompt) i inżynieria promptów?

meme code
meme code@memecode
ZOMBIE w Ruby. Co to jest?
3 maj 12:41

ZOMBIE w Ruby. Co to jest?

meme code
meme code@memecode
3 maj 13:13

Czym jest Garbage Collector w Ruby? Jak działa i do czego potrzebny jest GC?

meme code
meme code@memecode
Trochę o typach implementacji Ruby (CRuby (MRI), JRuby, Rubinius, TruffleRuby, mruby)
5 maj 12:36

Trochę o typach implementacji Ruby (CRuby (MRI), JRuby, Rubinius, TruffleRuby, mruby)

meme code
meme code@memecode
7 maj 07:24

Czym jest natywny kod maszynowy?

meme code
meme code@memecode
9 maj 12:43

[Fix] Rails Admin - niezdefiniowana lokalna zmienna lub metoda javascript_importmap_shim_nonce_configuration_tag

meme code
meme code@memecode
Czym jest dług techniczny (technical debt) w projektach IT?
13 maj 06:17

Czym jest dług techniczny (technical debt) w projektach IT?

meme code
meme code@memecode
13 maj 07:11

Co oznacza zakres (scope) w zarządzaniu projektami IT?

meme code
meme code@memecode
Co to jest "rozprzestrzenienie zakresu" (Scope Creep / Skołp krip)?
13 maj 07:20

Co to jest "rozprzestrzenienie zakresu" (Scope Creep / Skołp krip)?

meme code
meme code@memecode
Co oznacza "Nattywny"?
22 maj 07:01

Co oznacza "Nattywny"?

meme code
meme code@memecode
Jak działa 'rails console --sandbox'?
23 maj 19:39

Jak działa 'rails console --sandbox'?

meme code
meme code@memecode