Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

str::splitn(N, ' ') is slower than it ought to be #82471

Open
jeffsmith82 opened this issue Feb 24, 2021 · 0 comments
Open

str::splitn(N, ' ') is slower than it ought to be #82471

jeffsmith82 opened this issue Feb 24, 2021 · 0 comments
Labels
A-str Area: str and String C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@jeffsmith82
Copy link

I wrote a small benchmark and was surprised at how much slower it was using str::splitn rather than using bytes directly.

splitn
Time elapsed in parse_response() is: 2.290853462s

as bytes
Time elapsed in parse_response() is: 661.947666ms

Is it possible to do something similar to #46693 where if splitting on a single byte.

https://users.rust-lang.org/t/performance-comparison/56041/2

use std::time::{Duration, Instant};
fn main() {
    let response = String::from("HTTP/1.1 418 I'm a teapot\r\n");
    let mut res: (&str, &str, &str) = ("", "", "");
    let start = Instant::now();
    for _ in 0..100_000_000 {
        res = match parse_http(&response) {
            Ok(data) => data,
            Err(_) => {
                continue;
            }
        };
    }
    let duration = start.elapsed();

    println!("version:{}\ncode:{}\ndescription:{}\n", res.0, res.1, res.2);
    println!("Time elapsed in parse_response() is: {:?}", duration);
    
    let start2 = Instant::now();
    for _ in 0..100_000_000 {
        res = match parse_http2(&response) {
            Ok(data) => data,
            Err(_) => {
                continue;
            }
        };
    }
    let duration2 = start2.elapsed();

    println!("version:{}\ncode:{}\ndescription:{}\n", res.0, res.1, res.2);
    println!("Time elapsed in parse_response() is: {:?}", duration2);
}

fn parse_http(s: &str) -> Result<(&str, &str, &str), &str> {
    let mut parts = s.splitn(3, ' ');
    let version = parts.next().ok_or("No Version")?;
    let code = parts.next().ok_or("No status code")?;
    let description = parts.next().ok_or("No description")?;
    Ok((version, code, description))
}

fn parse_http2(s: &str) -> Result<(&str, &str, &str), &str> {
    let mut bytes = s.as_bytes().iter();
    let i = bytes.position(|b| *b == b' ').ok_or("No Version")?;
    let j = bytes.position(|b| *b == b' ').ok_or("No status code")? + i + 1;

    let version = &s[..i];
    let code = &s[(i + 1)..j];
    let description = &s[(j + 1)..];
    Ok((version, code, description))
}
@jonas-schievink jonas-schievink added C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Feb 24, 2021
@the8472 the8472 added the A-str Area: str and String label Feb 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-str Area: str and String C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants