为什么计时器显示的如此违反直觉?

Nur*_*yev 3 performance rust

我正在解析一些文本。我需要支持unicode文本,这就是为什么我要使用String::chars迭代器:

操场

use std::time::Instant;

fn main() {
    let text = "a".repeat(10000);
    let mut timer1 = 0;
    let mut timer2 = 0;

    let start1 = Instant::now();
    for pos in 1..10000 {
        let start2 = Instant::now();
        let ch = text.chars().nth(pos).unwrap();
        timer2 += start2.elapsed().as_millis();
    }
    timer1 += start1.elapsed().as_millis();

    println!("timer1: {} timer2: {}", timer1, timer2);
}
Run Code Online (Sandbox Code Playgroud)

输出示例:

timer1: 4276 timer2: 133
Run Code Online (Sandbox Code Playgroud)

当我认为它们应该彼此非常接近时,为什么timer2比令人难以置信的要小timer1

PS我已经知道那.nth很慢,不应该使用。

ask*_*sky 7

您遇到了解决问题。循环内部执行(平均)所需的时间少于一毫秒,因此start2.elapsed().as_millis()通常求值为0。要解决此问题,您可以在循环内部执行一些操作,而该操作甚至需要更长的时间,或者将分辨率从毫秒更改为更小的值。 ,例如微秒或纳秒。

切换到微秒会产生更一致的时间

use std::time::{Instant};

fn main() {
    let text = "a".repeat(10000);
    let mut timer1 = 0;
    let mut timer2 = 0;

    let start1 = Instant::now();
    for pos in 1..10000 {
        let start2 = Instant::now();
        let ch = text.chars().nth(pos).unwrap();
        timer2+=start2.elapsed().as_micros();
    }
    timer1+=start1.elapsed().as_micros();

    println!("timer1: {} timer2: {}", timer1, timer2);
}
Run Code Online (Sandbox Code Playgroud)

输出

timer1: 3511812 timer2: 3499669
Run Code Online (Sandbox Code Playgroud)

这个问题被标记为性能,所以我想指出,使用std::Instant是一种非常乏味的衡量性能的方法。更好的方法包括criteria.rsfiregraphcargo-bench

  • 我发表评论是因为我没有时间说出正确的答案。由于其他人花了时间,所以他们得到了赞扬和赞许是很公平的。在这里,有我的:) (8认同)