CRuby'de FFI hızını artırmanın bir yolu var mı?
- Ruby'de native kod çağırmanız gerektiğinde, mümkün olduğunca çok Ruby kodu yazmak daha iyidir. Çünkü YJIT, Ruby kodunu optimize edebilir ama C kodunu optimize edemez.
- Native kütüphaneleri çağırırken, işin çoğunu Ruby'de yapıp native fonksiyon çağrıları için basit bir API sunan bir native extension yazmak daha iyidir.
- FFI, native extension kadar performans sunmaz. Örneğin
strlen C fonksiyonunu FFI ile sarmaladığınızda, C extension'a kıyasla performans daha düşüktür.
Benchmark sonuçları
String#bytesize'ı doğrudan çağırmak en hızlısıdır ve bunu referans noktası olarak düşünebilirsiniz.
- C extension üzerinden
strlen çağrısı ikinci en hızlıdır; dolaylı olarak String#bytesize çağırmak ise onun ardından gelir.
- FFI implementasyonu en yavaşıdır. Bu da FFI üzerinden native fonksiyon çağırırken ciddi bir ek yük oluştuğunu gösterir.
Durumu değiştirmek mümkün mü?
- Chris Seaton'ın fikriyle, dış fonksiyonları çağırmak için JIT kodu üretme olasılığı araştırılıyor.
- FFI wrapper örneğinde,
attach_function çağrısı sırasında wrapper fonksiyon tanımlanırken gerekli makine kodu üretilebilir.
RJIT kullanımı
- RJIT, Ruby ile yazılmış ve Ruby ile birlikte gelen bir JIT derleyicisidir.
- 3rd party JIT derleyicilerin Ruby veri yapılarını kolayca eşleyebilmesi için RJIT bir gem olarak ayrıştırıldı.
- JIT entry function pointer'ı her zaman çalıştırılarak 3rd party JIT'in makine koduna kaydolabilmesi sağlanıyor.
Kavram kanıtı
- "FJIT" adlı küçük bir kavram kanıtı ile, çalışma anında makine kodu üretilerek dış fonksiyonlar çağrılabiliyor.
- Benchmark sonuçlarına göre FJIT'in ürettiği makine kodu, C extension'dan daha hızlı ve FFI çağrısından 2 kattan fazla daha hızlı.
Sonuç
- Bu, C extension ile aynı hızın (hatta daha yüksek hızın) korunurken mümkün olduğunca çok Ruby kodu yazılabileceğini gösteriyor.
- Ruby, FFI olmadan native kod çağırabilme avantajına sahip olabilir.
Dikkat edilmesi gerekenler
- Şu anda yalnızca ARM64 platformuyla sınırlı. x86_64 backend'inin eklenmesi gerekiyor.
- Tüm parametre türleri ve dönüş türleri desteklenmiyor. Yalnızca tek parametre ve tek dönüş değeri işlenebiliyor.
- Ruby'nin
--rjit --rjit-disable bayraklarıyla çalıştırılması gerekiyor. Kokubun'un özelliği uygulandığında bu sorun çözülecek.
- Şu anda yalnızca Ruby head üzerinde çalışabiliyor.
1 yorum
Hacker News görüşleri
Java Constraint Solver (Timefold) ile CPython arasında fonksiyon çağrıları için yoğun biçimde FFI ile uğraşmak gerekti
Rails At Scale ve byroot'un blogu sayesinde şu sıralar Ruby internalleri ve performansı üzerine derinlemesine tartışmalara ilgi duymak için iyi bir zaman
Dış fonksiyon çağrıları için 3rd party kütüphane çağırmak yerine kodun JIT derlenip derlenemeyeceğine dair bir soru
JVMCI kullanarak anında arm64/amd64 kodu üretip JNI olmadan native kütüphaneleri çağıran bir kütüphane hakkında bilgi: bağlantı
"Mümkün olduğunca çok Ruby yazın; özellikle de YJIT Ruby kodunu optimize edebilirken C kodunu optimize edemediği için" görüşü
10 yıldan uzun süredir Ruby kullanıyorum ve son gelişmeleri görmek gerçekten çok ilginç
Neden JIT derlemeye ihtiyaç duyulduğuna dair soru
FFI - Foreign Function Interface, yani Ruby'den C çağırma yöntemi
Bunun zaten libffi'nin yaptığı şey olup olmadığına dair soru
Sanırım insanların tenderlovemaking.com'a neden gitmediğini anlıyorum