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

Продуктивність у циклах vs. ітераторах

Щоб визначити, чи використовувати цикли або ітератори, вам потрібно знати, яка реалізація є швидшою: версія функції search з явним циклом for або версія з ітераторами.

Ми провели benchmark, завантаживши весь вміст Пригоди Шерлока Холмса сера Артура Конана Дойла в String і шукаючи слово the у вмісті. Ось результати benchmark для версії search, що використовує цикл for, і версії, що використовує ітератори:

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

Дві реалізації мають подібну продуктивність! Ми не будемо пояснювати код benchmark тут, тому що мета не в тому, щоб довести, що дві версії еквівалентні, а в тому, щоб отримати загальне уявлення про те, як ці дві реалізації порівнюються за продуктивністю.

Для більш комплексного benchmark ви повинні перевіряти, використовуючи різні тексти різного розміру як contents, різні слова та слова різної довжини як query, і всілякі інші варіації. Суть у тому: ітератори, хоча й є абстракцією високого рівня, компілюються приблизно в той самий код, ніби ви написали нижчорівневий код самостійно. Ітератори — це одна з абстракцій нульової вартості Rust, під чим ми маємо на увазі, що використання цієї абстракції не накладає жодних додаткових runtime-витрат. Це аналогічно тому, як Б’ярне Страуструп, оригінальний дизайнер і реалізатор C++, визначає zero-overhead у своїй ключовій доповіді ETAPS 2012 року “Foundations of C++”:

Загалом, реалізації C++ дотримуються принципу zero-overhead: За те, чим ви не користуєтеся, ви не платите. І далі: Те, чим ви користуєтеся, ви не змогли б вручну написати краще.

У багатьох випадках код Rust, що використовує ітератори, компілюється в той самий assembly, який би ви написали вручну. Такі оптимізації, як розгортання циклів і усунення перевірки обмежень під час доступу до масивів, застосовуються й роблять отриманий код надзвичайно ефективним. Тепер, коли ви це знаєте, ви можете використовувати ітератори та замикання без страху! Вони роблять код схожим на вищорівневий, але не накладають runtime-покарання за це.

Підсумок

Замикання та ітератори — це можливості Rust, натхненні ідеями мов функціонального програмування. Вони сприяють здатності Rust чітко виражати ідеї високого рівня з продуктивністю низького рівня. Реалізації замикань та ітераторів такі, що runtime-продуктивність не зазнає впливу. Це частина мети Rust — прагнути надавати абстракції нульової вартості.

Тепер, коли ми покращили виразність нашого проєкту I/O, давайте розглянемо деякі інші можливості cargo, які допоможуть нам поділитися проєктом зі світом.