簡體   English   中英

為什么 Rust 中的迭代器在我迭代它們時看起來非常慢?

[英]Why are iterators in Rust seemingly very slow when I iterate over them?

我有一個使用 mmap 讀取的大文件。 我想在每一行上做一些操作,所以我在上面調用 split() ,這給了我每行的迭代器:

let file = File::open("myfile").unwrap();
let mmap = unsafe { MmapOptions::new().map(&file).unwrap() };
//splitting by newline
let iter = mmap.split(|elem| elem == &b'\n');

這工作正常,不會給我任何問題 - 運行速度非常快。

但是,當我通過迭代器 go 時,它會跳轉並且通過 for 循環到 go 所需的時間大約是讀取和拆分所需時間的 4 倍。

此外,這無需處理該行或在 for 循環內執行任何操作:

for elem in iter {
  //process the line
}

由於性能是一個問題 - 我發現它能夠非常快速地讀取和拆分文件很奇怪,但是,當我通過迭代器 go 時它變得非常慢。 我錯過了什么嗎? 我對 rust 的了解也很有限,所以不確定我是否做錯了什么。 有什么可以幫助我優化這一點並讓我更快的訪問時間嗎?

此外,在我的情況下,並行迭代器並沒有太大幫助——它們增加的開銷是不值得的。

整個文件:

use memmap::MmapOptions;
use std::fs::File;
use std::time::{Duration, Instant};

fn main() {

    let now = Instant::now();
    let file = File::open("myfile").unwrap();
    let mmap = unsafe { MmapOptions::new().map(&file).unwrap() };
    let iter = mmap.split(|elem| elem == &b'\n');

    /*
    for elem in iter {
      //do nothing
    }
    */
    println!("{:?}", now.elapsed());
}

如果我取消注釋 for 循環,它會慢 4 倍。 我正在使用 --release 標簽構建,所以這不是問題。

該代碼僅在取消注釋 for 循環時看起來很慢,因為它不會做任何其他事情。 迭代器是惰性的,僅在消耗時執行一些活動。

引用Rust 編程語言第 13 章第 2 節中的相關部分:

在 Rust 中,迭代器是惰性的,這意味着它們在您調用消耗迭代器的方法以將其用完之前無效。 [...] 在迭代器上調用next方法會更改迭代器用來跟蹤它在序列中的位置的內部 state。 換句話說,此代碼消耗或用完迭代器

for 循環是使用迭代器的構造示例。 在內存映射數據上調用.split()只會為該迭代器創建一個適配器(請注意,這並不意味着它會創建多個迭代器)。 正如本書中所描述的,適配器是使用迭代器的一種常見方式。

Iterator trait 上定義的其他方法,稱為迭代器適配器,允許您將迭代器更改為不同類型的迭代器。 您可以將多個調用鏈接到迭代器適配器,以一種可讀的方式執行復雜的操作。 但是因為所有的迭代器都是惰性的,所以您必須調用其中一個使用適配器的方法來從對迭代器適配器的調用中獲取結果。

因此,該示例不會急切地在 memory 中創建這些拆分,並且該程序僅在存在 for 循環或以其他方式消耗迭代器時才做一些有價值的事情。

也可以看看:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM