问题
I am making a parser of some text. I need to support unicode texts, that's why I am using the String::chars iterator:
playground
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);
}
Example output:
timer1: 4276 timer2: 133
Why is timer2 unbelievably less than timer1, when I believe they should be very close to each other?
P.S. I know already that .nth is slow, and shouldn't be used.
回答1:
You are running into a resolution problem. The inside of the loop takes (on average) less than one millisecond to execute, so start2.elapsed().as_millis() usually evaluates to 0. To fix this problem, you could do some operation inside the loop that takes even longer, or change your resolution from milliseconds to something smaller, like microseconds or nanoseconds.
switching to microseconds yields a more consistent time
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);
}
output
timer1: 3511812 timer2: 3499669
This question was tagged performance, so I'd like to point out that using std::Instant is a very tedious way to measure performance. Better ways include criterion.rs, flamegraph and cargo-bench.
来源:https://stackoverflow.com/questions/59044638/why-is-what-timers-show-so-counter-intuitive