- Datalog mantıksal programlama ile Rust'ın verimliliğini birleştirerek, sade ama kullanışlı ve performansı da gözeten etkileşimli bir Datalog motorunun geliştirme süreci ayrıntılı biçimde paylaşılıyor
- Sezgisel bir CLI ortamında kural (rule) ve olgu (fact) gerçek zamanlı olarak eklenip genişletilebiliyor; büyük veri yükleme, dinamik kural girişi ve hızlı sorgu performansı deneyimlenebiliyor
- Ayrıştırma (Parsing), veri temsili (Representation), kural değerlendirme (Planning/Evaluation) adım adım Rust kodlarıyla anlatılarak gerçek bir uygulamanın nasıl geliştirileceği gösteriliyor
- Optimize edilmemiş basit bir uygulamadan başlayıp performans ve yapıyı kademeli olarak iyileştirme süreci üzerinden veri paralelliği/join optimizasyonu gibi ileri düzey mantıklar da öğrenilebiliyor
- Büyük veri kümelerine dayalı program analizi (Nullability, Aliasing vb.) örnekleri gerçekten çalıştırılarak performans ve bellek sorunları, sorgu optimizasyonu ve join-plan iyileştirme bilgileri paylaşılıyor
Giriş: Rust'ta Datalog mantıksal programlama deneyi
- Memorial Day döneminde Minnowbrook konferansında çeşitli mantıksal programlama (Datalog vb.) uygulamaları ve tartışmalar yapıldı
- Mevcut Datalog araçlarında (Soufflé, ctdal vb.) gerçek kullanım/genişletilebilirlik/performans açısından sınırlamalar görüldü; pratik bir araca olan ihtiyaç öne çıktı
- Yazar, doğrudan Rust ile sadelik/kullanılabilirlik/performansın hepsini karşılayan bir Datalog yorumlayıcısı (
datatoad) geliştirmeye karar verdi
- Projenin hedefi: CLI üzerinde büyük hacimli veriyi hızlı yüklemek, kuralları dinamik olarak ekleyip değiştirmek, sonuçları gerçek zamanlı görmek ve sorgu performansını güvenceye almak
Datalog'un temel kavramları
- Datalog, kural (Head :- Body) biçimindeki mantıksal ifadeleri temel alır ve verilen fact ile rule'lar üzerinden çıkarılabilecek tüm olguları otomatik olarak türetir
- Kurallar (ör.
tri(a, b, c) :- edge(a, b), edge(b, c), edge(a, c)) değişkenler/literallerden oluşur
- fact, koşulsuz doğru kabul edilen bir değerdir (ör.
edge(1, 2) :- .)
- Datalog'un güçlü yanı: yeni kurallar eklendiğinde çıkarılabilir bilgi kümesinin artması (monotonluk) ve kural/olgu sırasından bağımsız olarak aynı sonucun elde edilmesi (yakınsama)
- Rust tarafında kurallar ve fact'ler Atom/Rule/Term yapılarıyla temsil edilir, fact kümeleri ise relation bazında yönetilir
Temel yapı tasarımı
Veri temsili
- Fact, başlangıçta
Vec<String> olarak; fact kümesi ise BTreeMap<String, Vec<Fact>> gibi yapılarla tasarlandı
- Büyük veri optimizasyonu için columnar (sütun odaklı) veri yapısı benimsendi ve allocation overhead en aza indirildi
- FactContainer: sıralanmış ve tekilleştirilmiş fact kümesi, append-only yapı
- FactLSM: FactContainer'ları çok katmanlı yöneten LSM (Log-structured merge-tree) yaklaşımı; ekleme ile sıralama/birleştirme işlemlerini verimli hale getiriyor
- FactSet: fact yaşam döngüsünü (yeni eklenen, yakın zamanda türetilen, kararlı hale gelen fact'ler) yöneterek yinelenen hesaplamaları ve gereksiz bellek israfını önlüyor
Kural uygulama ve çıkarım
- Her kural için bir JoinPlan oluşturuluyor ve uygun sütun sırası/anahtar kombinasyonlarına dayalı merge join ile çıkarım yapılıyor
- merge join: body atomlarındaki anahtar sütunlar sıralanıyor; yalnızca join anahtarları eşleştiğinde yeni fact türetiliyor ve böylece performans en üst düzeye çıkarılıyor
- FactSet'in stable/recent/to_add yapısı kullanılarak önceden türetilmiş fact'lerle yeni fact'ler ayrıştırılıyor, böylece gereksiz yeniden hesaplamalar önleniyor (diferansiyel değerlendirme)
.update() döngüsü: yeni fact üretimi durana kadar tüm kurallar tekrar tekrar uygulanıyor; fixpoint'e ulaşana dek çıkarım sürüyor
Parser uygulaması
- Soufflé tarzı sözdizimi (
?var, :-, ., , vb.) destekleniyor; tokenizer ve parser doğrudan Rust ile yazılmış
- Hata durumunda güvenli biçimde None döndüren, deneysel ortama uygun sade bir parser tasarımı tercih edilmiş
Performans optimizasyonu ve gerçek analiz örnekleri
Nullability analizi (Reachability)
- Büyük veri kümelerinde (ör. httpd_df) değer kopyalama/taşıma yollarını izlemek için Datalog kuralları tanımlanıyor ve performans ölçülüyor
- Farklı kural yazım kalıpları arasında çok büyük performans farkları oluşuyor (değişken bağlama/sütun sırası/join planına bağlı geçici relation üretimi vb.)
- Verinin başlangıç biçimi ve join stratejisine göre çalışma süresi ile bellek kullanımı onlarca kat değişebiliyor; bu da sorgu optimizasyonunun önemini doğrudan gösteriyor
- Optimizasyon uygulandığında mevcut C++ tabanlı araçlara (Graspan vb.) kıyasla 10 ila 80 katı aşan performans artışı görüldü
Aliasing analizi (Points-to)
- Aliasing/pointer izleme analizi için karmaşık Datalog kalıpları uygulanıyor; makalelerdeki (Graspan, Zheng-Rugina vb.) sorgularla aynı sorgular çalıştırılıyor
- Datalog kuralları içindeki tekrar (
^*), opsiyon (^?), transpoz (^T) işlemleri açık özyineleme/union olarak genişletiliyor
- Ara sonuçların (relation alias, geçici join vb.) adlandırılması ve yeniden kullanımı, tüm sorgu planının verimliliğinde ve kaynak tüketiminde büyük fark yaratıyor
- Sorgu planı optimize edilmeden büyük ara sonuçlar üretilirse performans düşüşü ve bellek patlaması yaşanabiliyor (ör. V relation)
- Yalnızca gerekli sonuçları üreten "demand-driven" yaklaşım (magic set dönüşümü) tartışılıyor; gerçek sorgu planı dönüşümleri ve performans iyileştirme ihtimali sunuluyor
Rust ile doğrudan deney yaparak çıkarılan dersler
- Datalog motoru performansının özü veri temsili (columnar/LSM), diferansiyel çıkarım ve join plan optimizasyonunda yatıyor
- Kuralları yalnızca mekanik biçimde yazmak, gereksiz ara veri üretimine ve kaynak israfına yol açabiliyor; optimizasyon şart
- Rust ile doğrudan deney yapıldığında, gerçek veri kümelerinde milyonlarca/on milyonlarca satırlık fact'i verimli biçimde yönetip ölçeklenebilirlik ile çıkarım hızını aynı anda elde etmek mümkün
- CLI ortamında büyük veri yükleme, gerçek zamanlı kural ekleme ve sonuç inceleme işlemleri kolayca denenebiliyor
- Query optimizer'ın rolü, bushy-tree join kullanımı (ara sonuçlardan yararlanma), gereksiz relation üretmekten kaçınma alışkanlığı gibi noktalar, gerçek Datalog yazımı ve işletimi için önemli içgörüler sunuyor
Gelecekteki genişleme alanları
- Disk spill, çoklu worker/prosesle dağıtık genişleme, streaming join, özel derleme optimizasyonları gibi araştırma konuları hâlâ açık duruyor
- Büyük ölçekli program analizi, grafik/ilişkisel çıkarım, statik analiz, veri akışı izleme gibi pratik alanlarda Rust tabanlı Datalog'un kullanım potansiyeli yüksek
1 yorum
Hacker News yorumu