- Menggabungkan pemrograman logika Datalog dengan efisiensi Rust, dan membagikan secara rinci proses pengembangan mesin Datalog interaktif yang sederhana, mudah digunakan, sekaligus mempertimbangkan performa
- Dalam lingkungan CLI yang intuitif, rule dan fact dapat ditambahkan/diperluas secara real-time, sekaligus merasakan pemuatan data dalam jumlah besar, input rule dinamis, dan performa kueri yang cepat
- Parsing, representasi data, dan evaluasi rule (Planning/Evaluation) dijelaskan langkah demi langkah bersama kode Rust sehingga pembaca dapat mempelajari cara implementasinya secara nyata
- Dimulai dari implementasi sederhana yang belum dioptimalkan lalu secara bertahap meningkatkan performa dan strukturnya, sehingga logika lanjutan seperti pemrosesan paralel data dan optimasi join juga bisa dipelajari
- Menjalankan langsung contoh analisis program berbasis dataset besar (Nullability, Aliasing, dll.), sambil membagikan wawasan tentang performa, isu memori, optimasi kueri, dan peningkatan join-plan
Pendahuluan: bereksperimen dengan pemrograman logika Datalog di Rust
- Selama periode Memorial Day, dilakukan berbagai praktik dan diskusi tentang pemrograman logika seperti Datalog di konferensi Minnowbrook
- Ditemukan keterbatasan pada alat Datalog yang ada (Soufflé, ctdal, dll.) dari sisi penggunaan nyata, ekstensibilitas, dan performa, sehingga kebutuhan akan alat yang lebih praktis menjadi menonjol
- Penulis memutuskan untuk mengimplementasikan sendiri interpreter Datalog (
datatoad) di Rust yang memenuhi kesederhanaan, kemudahan penggunaan, dan performa sekaligus
- Tujuan proyek: memuat data berukuran besar dengan cepat dari CLI, menambah/mengubah rule secara dinamis, melihat hasil secara real-time, dan tetap mendapatkan performa kueri yang baik
Konsep dasar Datalog
- Datalog adalah sistem yang secara otomatis menurunkan semua fakta yang dapat disimpulkan dari fact dan rule yang diberikan, berdasarkan pernyataan logika berbentuk rule (
Head :- Body)
- Rule (contoh:
tri(a, b, c) :- edge(a, b), edge(b, c), edge(a, c)) tersusun dari variabel dan literal
- Fact adalah nilai yang benar tanpa syarat (contoh:
edge(1, 2) :- .)
- Kekuatan Datalog: saat rule ditambahkan, himpunan informasi yang dapat diinferensikan bertambah (monotonisitas), dan hasil yang diperoleh tetap sama terlepas dari urutan rule/fact (konvergensi)
- Di Rust, rule dan fact direpresentasikan dengan struct
Atom/Rule/Term, dan himpunan fact dikelola per relation
Desain struktur inti
Representasi data
- Fact awalnya dirancang sebagai
Vec<String>, dan himpunan fact sebagai BTreeMap<String, Vec<Fact>> dan sejenisnya
- Untuk mengoptimalkan data berukuran besar, diperkenalkan struktur data columnar guna meminimalkan alloc overhead
- FactContainer: himpunan fact yang sudah diurutkan/dideduplikasi, dengan struktur append-only
- FactLSM: pendekatan LSM (Log-structured merge-tree) yang mengelola
FactContainer dalam beberapa lapisan untuk mengefisienkan penyisipan serta pengurutan/penggabungan
- FactSet: mengelola lifecycle fact (baru ditambahkan, baru diturunkan, fact yang sudah stabil) untuk mencegah perhitungan duplikat dan pemborosan memori yang tidak perlu
Penerapan rule dan inferensi
- Setiap rule menghasilkan
JoinPlan, lalu melakukan inferensi dengan metode merge join berdasarkan urutan kolom dan kombinasi key yang sesuai
- Merge join: setelah kolom key pada tiap body atom diurutkan, fact baru hanya diturunkan ketika key join cocok, untuk memaksimalkan performa
- Dengan memanfaatkan struktur stable/recent/to_add pada
FactSet, fact yang sudah diturunkan dan fact baru dipisahkan untuk mencegah komputasi ulang yang tidak perlu (evaluasi diferensial)
- Loop
.update(): semua rule diterapkan berulang sampai tidak ada lagi fact baru yang diturunkan, dan inferensi diulang hingga mencapai fixpoint
Implementasi parser
- Mendukung sintaks bergaya Soufflé (
?var, :-, ., ,, dll.), dengan tokenizer/parser yang ditulis langsung di Rust
- Saat terjadi error, parser dengan aman mengembalikan
None, sebagai desain parser sederhana yang cocok untuk lingkungan eksperimental
Optimasi performa dan contoh analisis nyata
Analisis Nullability (Reachability)
- Pada dataset besar (misalnya
httpd_df), didefinisikan rule Datalog untuk melacak jalur penyalinan/perpindahan nilai dan diukur performanya
- Perbedaan performa bisa sangat besar tergantung pola penulisan rule (binding variabel/urutan kolom/kemunculan relation sementara berdasarkan join plan, dll.)
- Bergantung pada bentuk awal data dan strategi join, waktu eksekusi serta penggunaan memori dapat berbeda hingga puluhan kali lipat, sehingga pentingnya optimasi kueri dapat dirasakan langsung
- Setelah optimasi diterapkan, terkonfirmasi peningkatan performa 10 hingga lebih dari 80 kali dibanding alat berbasis C++ yang ada (seperti Graspan)
Analisis Aliasing (Points-to)
- Mengimplementasikan pola Datalog yang kompleks untuk analisis aliasing/pelacakan pointer, dan menjalankan kueri yang sama seperti pada makalah (Graspan, Zheng-Rugina, dll.)
- Operasi iterasi (
^*), opsional (^?), dan transpose (^T) dalam rule Datalog diperluas menjadi rekursi/union eksplisit
- Bergantung pada desain penamaan/penggunaan ulang hasil antara (relation alias, temp join, dll.), efisiensi dan konsumsi sumber daya seluruh query plan dapat sangat berbeda
- Jika hasil antara yang besar dibuat tanpa optimasi query plan, performa akan menurun dan penggunaan memori bisa melonjak drastis (contoh: relation
V)
- Dibahas pendekatan "demand-driven" (transformasi magic set) yang hanya menghasilkan hasil yang diperlukan, serta ditunjukkan kemungkinan perubahan query plan dan peningkatan performa nyata
Pelajaran yang didapat dari eksperimen langsung di Rust
- Kunci performa mesin Datalog ada pada representasi data (columnar/LSM), inferensi diferensial, dan optimasi join plan
- Jika rule hanya ditulis secara mekanis, hal itu dapat menyebabkan pembentukan data antara yang tidak perlu dan pemborosan sumber daya, sehingga optimasi menjadi penting
- Melalui eksperimen langsung di Rust, fact dengan ratusan juta hingga puluhan juta row pada dataset nyata dapat dikelola secara efisien, sambil mencapai skalabilitas dan kecepatan inferensi sekaligus
- Dalam lingkungan CLI, eksperimen seperti memuat data besar, menambahkan rule secara real-time, dan memeriksa hasil dapat dilakukan dengan mudah
- Peran query optimizer, bushy-tree join (memanfaatkan hasil antara), dan kebiasaan menghindari pembuatan relation yang tidak diperlukan memberi banyak implikasi praktis untuk penulisan dan operasional Datalog
Tugas pengembangan selanjutnya
- Masih ada topik penelitian yang tersisa seperti disk spill, ekspansi terdistribusi multi-worker/proses, streaming join, dan optimasi kompilasi kustom
- Rust Datalog memiliki potensi pemanfaatan tinggi di bidang nyata seperti analisis program skala besar, inferensi graf/relasional, analisis statis, dan pelacakan aliran data
1 komentar
Komentar Hacker News