键盘快捷键

按 ← 或 → 在章节之间导航

按 S 或 / 在本书中搜索

按 ? 显示此帮助

按 Esc 隐藏此帮助

循环与迭代器的性能

要决定是使用循环还是迭代器,你需要知道哪种实现更快:是使用显式 for 循环的 search 函数版本,还是使用迭代器的版本。

我们运行了一个基准测试,将阿瑟·柯南·道尔爵士的《福尔摩斯探案集》的全部内容加载到一个 String 中,并在内容中查找单词 the。以下是使用 for 循环的 search 版本与使用迭代器的版本的基准测试结果:

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

这两种实现的性能差不多!我们不会在这里解释基准测试代码,因为重点不是要证明两个版本等价,而是要大致了解这两种实现在性能方面的对比。

为了进行更全面的基准测试,你应该使用各种不同大小的文本作为 contents,使用不同的单词和不同长度的单词作为 query,以及各种其他变化来检查。要点是:迭代器虽然是一种高级抽象,但编译后得到的代码与你亲手编写的底层代码大致相同。迭代器是 Rust 的零成本抽象之一,我们的意思是使用该抽象不会带来额外的运行时开销。这类似于 C++ 的原始设计者和实现者 Bjarne Stroustrup 在其 2012 年 ETAPS 主题演讲“C++ 的基础”中对零开销的定义:

通常,C++ 实现遵循零开销原则:你不使用的东西,就不用为它付出代价。而且更进一步:你使用的东西,你也不可能手写得更好。

在许多情况下,使用迭代器的 Rust 代码编译后与你手写的汇编代码相同。循环展开和消除数组访问的边界检查等优化得以应用,使得生成的代码非常高效。现在你知道了这一点,可以放心地使用迭代器和闭包了!它们让代码看起来更高级,但这样做不会带来运行时性能的损失。

总结

闭包和迭代器是受函数式编程语言思想启发的 Rust 特性。它们有助于 Rust 以低级别的性能清晰地表达高级概念的能力。闭包和迭代器的实现使得运行时性能不会受到影响。这是 Rust 努力提供零成本抽象这一目标的一部分。

既然我们已经提高了 I/O 项目的表达能力,让我们看看 cargo 的一些更多特性,它们将帮助我们把这个项目分享给世界。