0

I am trying to process vector with while loop. currently it is sequential taking each element at a time. Is there a way to process vector elements in parallel with rayon and get the same result. Will it increase the performance of the code given below? Basically I am getting continuous messages from tcp client and converting them in to vector and then process them. I want to make processing part faster. sample code is given below.

fn main() {
    let r = process(false);
}

fn process (choice: bool) -> i32 {
    let mut i = 0;
    let my_string = "s1/s2/s3/s4/s5/s6/s7".to_string();
    let my_vector: Vec<&str> = my_string.as_str().split("/").collect();
    let mut tag_path = "MyString".to_string();
    let mut message = "Variable = ".to_string();
    let mut root_path = "".to_string();
    return if !choice {
        while i < my_vector.len() {
            tag_path += "/";
            tag_path += my_vector[i];
            if i != my_vector.len() - 1 {
                message = tag_path.clone();
                let my_target_1 = tag_path.clone() + ":";
                println!("{}", my_target_1)
            } else {
                let my_target_2 = tag_path.clone() + ",";
                println!("{}", my_target_2);
            }
            root_path = message.clone();
            i += 1;
        }
        1
    } else {
        0
    }
}

JNP
  • 153
  • 2
  • 8
  • It's really not clear what you're actually trying to achieve with the example (which has a bunch of seemingly useless / unused variables and doesn't seem to do anything useful), so it's hard to answer. Why are you using a `while` loop in the first place? rayon works entirely off of iterators, so if it's not possible to express your workload using that you're done for. Rayon also works concurrently so if you need to process your items purely sequentially, that's not going to fly. But we've got no idea about either from what you posted. And have you at least looked at rayon already? – Masklinn Jul 26 '21 at 07:24
  • I would start by removing the unnecessary cloning. For example, you could use `println!("{}:", tag_path)` instead of cloning it into a separate `my_target` variable. – isekaijin Jul 26 '21 at 07:28
  • Also, Rust is not JavaScript or Python, so, even if you could not do away with the variables `my_target_1` and `my_target_2` (as my previous comment shows), you could still rename both to `my_target` and they would not collide or anything like that. – isekaijin Jul 26 '21 at 07:30
  • What I would probably do is, instead of splitting `my_string`, I would just identify the positions where the `'/'`s appear, and then take substrings of the appropriate lengths. The substrings could be represented as slices of the original string, so that would eliminate some unnecessary cloning as well. – isekaijin Jul 26 '21 at 07:34

1 Answers1

0

Your code is not slow because you are missing parallelism opportunities, but rather because you are copying ever longer strings in a way that is reminiscent of Shlemiel the Painter's algorithm. Remember that copying strings runs in linear time in the length of the string.

(Kids, this is why basic computer science is so important!)

Since some parts of your snippet are irrelevant to your actual problem (e.g., the choice argument), I have taken the liberty of removing them from my answer. After simplifying your code, what I obtained is this:

fn main() {
    let domain = "example.com";
    let path = "s1/s2/s3/s4/s5/s6/s7";
    let matches = path.match_indices('/');
    
    for (pos, _) in matches {
        println!("{}/{}:", domain, &path[0..pos]);
    }
    
    println!("{}/{},", domain, path)
}

To print a prefix of the full path, you just need to take a slice starting at the beginning of the path (i.e., the 0-th character) and ending just before the corresponding '/' (i.e., the pos-th character). This explains the line in the for loop.

isekaijin
  • 19,076
  • 18
  • 85
  • 153