For loops : faster iterations, cleaner code

Hi,

I've been messing around with for loops in my code. Basically, I often have begin and end coordinates from multiple arrays that I need to move around. Example:

let a : Vec<u8> = ....
let b : Vec<u8> = ....
let c : Vec<u8> = ....
let d : Vec<u8> = ....

// and then I need to copy segment a[x..y] -> c[i..j]
// and so on

What I use are for loops and then copy character by character. I figured It is the fastest way:

use std::time::Instant;

fn main() {
    let ext = |v: &mut Vec<u8>, ev: &Vec<u8>, b: usize| -> usize {
        let mut x = b;
        for i in ev.iter() {
            v[x] = *i;
            x += 1;
        }
        x
    };
    {
        let before = Instant::now();

        let mut a = vec![0u8; 2000000000];
        for i in 0..a.len() {
            a[i] = 9u8;
        }

        println!("Elapsed time  a): {:.2?}", before.elapsed());
    }

    {
        let before = Instant::now();
        let a = vec![9u8; 10];
        let mut b = Vec::new();
        for i in 0..200000000 {
            b.extend(a.clone());
        }
        println!("Elapsed time b): {:.2?}", before.elapsed());
    }

    {
        let before = Instant::now();
        let a = vec![9u8; 10];
        let mut b = vec![0u8; 2000000000];
        let mut y = 0;
        for i in 0..200000000 {
            y = ext(&mut b, &a, y);
        }
        println!("Elapsed time c): {:.2?}", before.elapsed());
    }

    {
        let before = Instant::now();
        let mut b = Vec::with_capacity(2000000000);
        for i in 0..2000000000 {
            b.push(9u8);
        }
        println!("Elapsed time d): {:.2?}", before.elapsed());
    }
}

Runtimes:

Elapsed time a): 949.04ms
Elapsed time b): 6.08s
Elapsed time c): 1.52s
Elapsed time d): 4.81s

But having these for loops looks nasty... What I consider clean, is the extend method but it's 6x slower and has 30-40% larger memory footprint than "a)" is there some other way to extend a vector without directly copy/pasting characters as in case of for loops?

thnx in advance :slight_smile:

In b) you are cloning the a vector on every iteration. Don't do that

let before = Instant::now();
let a = vec![9u8; 10];
let mut b: Vec<u8> = Vec::new();
for i in 0..200000000 {
    b.extend(&a);
}
println!("Elapsed time b): {:.2?}", before.elapsed());

You may also like this:

let before = Instant::now();
let mut b = Vec::with_capacity(2000000000);
b.extend((0..2000000000).map(|_| 9u8));
println!("Elapsed time e): {:.2?}", before.elapsed());

Anyway this kinda sounds like an XY problem. Is filling a vector with all nines the problem you are trying to solve? You can do that with vec![9u8; 2000000000].

1 Like

well i am trying to copy a slice from one vec to another starting at x and ends at y... so yes, it nos just a simple copy ... sorry but i did not know about e) :blush:

I recommend the copy_from_slice method. Note that you can call it like this:

(&mut vec[a..b]).copy_from_slice(&vec2[x..y]);
3 Likes

For special needs there is also the drain() method that takes out a slice from the and rearranges the original vector. It is not exactly what you are asking, but is good to know.

2 Likes