Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Membandingkan Performa: Loops vs. Iterators

Buat menentukan apakah kita sebaiknya memakai loops atau iterators, kita perlu tahu implementasi mana yang lebih cepat: versi fungsi search yang memakai for loop eksplisit atau versi yang memakai iterators.

Kita menjalankan sebuah benchmark (pengujian performa) dengan memuat seluruh isi buku The Adventures of Sherlock Holmes karya Sir Arthur Conan Doyle ke dalam sebuah String dan mencari kata the di dalam isinya. Berikut adalah hasil dari benchmark pada fungsi search versi for loop dan versi iterators:

test bench_search_for  ... bench:  19,620,300 ns/iter (+/- 915,700)
test bench_search_iter ... bench:  19,234,900 ns/iter (+/- 657,200)

Kedua implementasi ini punya performa yang mirip! Kita tidak bakal menjelaskan kode benchmark-nya di sini karena tujuannya bukanlah buat membuktikan kalau kedua versi itu persis ekuivalen, tapi buat ngasih gambaran umum soal gimana perbandingan performa kedua implementasi ini.

Untuk benchmark yang lebih komprehensif, kita sebaiknya menguji dengan memakai berbagai teks dari berbagai ukuran sebagai contents, kata yang berbeda-beda dan kata dengan panjang yang beda-beda sebagai query, dan berbagai jenis variasi lainnya. Poin utamanya adalah ini: iterators, meskipun merupakan sebuah abstraksi tingkat tinggi (high-level abstraction), bakal di-compile menjadi kode yang kurang lebih sama seperti kalau kita menulis sendiri kode tingkat rendah (lower-level code)-nya secara manual. Iterators adalah salah satu dari zero-cost abstractions (abstraksi tanpa biaya) di Rust, yang maksudnya adalah penggunaan abstraksi tersebut tidak menambahkan beban (overhead) apa pun pas runtime. Ini analog dengan gimana Bjarne Stroustrup, perancang dan pengimplementasi asli dari C++, mendefinisikan zero-overhead di “Foundations of C++” (2012):

Secara umum, implementasi C++ mematuhi prinsip zero-overhead: Apa yang tidak kita pakai, kita tidak perlu membayarnya. Dan lebih jauh lagi: Apa yang kita pakai, kita tidak bakal bisa nulis kodenya secara manual dengan lebih baik lagi.

Di banyak kasus, kode Rust yang memakai iterators di-compile menjadi kode assembly (bahasa rakitan) yang sama persis kayak yang bakal kita tulis pakai tangan sendiri. Berbagai optimasi kayak loop unrolling dan menghilangkan pengecekan batas (bounds checking) pada akses array bakal diterapkan dan membikin kode akhirnya jadi sangat efisien. Sekarang karena kita sudah tahu hal ini, kita bisa memakai iterators dan closures tanpa rasa takut! Mereka bikin kode kelihatan seperti di tingkat yang lebih tinggi (higher level) tapi tidak mengenakan hukuman performa (performance penalty) pas runtime karena ngelakuin hal tersebut.

Ringkasan

Closures dan iterators adalah fitur-fitur Rust yang terinspirasi dari ide-ide bahasa pemrograman fungsional. Mereka berkontribusi pada kemampuan Rust buat mengekspresikan ide-ide tingkat tinggi (high-level ideas) dengan jelas sembari mempertahankan performa tingkat rendah (low-level performance). Implementasi dari closures dan iterators dirancang sedemikian rupa sehingga performa pas runtime tidak terpengaruh. Ini adalah bagian dari tujuan Rust buat berjuang menyediakan zero-cost abstractions.

Sekarang setelah kita meningkatkan kemampuan ekspresi dari project I/O kita, mari kita lihat beberapa fitur cargo lainnya yang bakal membantu kita membagikan project kita dengan dunia.