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

Formatting numbers is slow #19218

Closed
mahkoh opened this Issue Nov 22, 2014 · 2 comments

Comments

Projects
None yet
5 participants
@mahkoh
Copy link
Contributor

mahkoh commented Nov 22, 2014

test fast_u64_format   ... bench:     19385 ns/iter (+/- 442)
test stdlib_u16_format ... bench:     79955 ns/iter (+/- 251)
#[inline(never)]
fn utoa(mut n: u64, buf: &mut [u8]) -> Result<uint, uint> {
    let num_digits = match n {
        0u64                    ... 9u64                    => 1,
        10u64                   ... 99u64                   => 2,
        100u64                  ... 999u64                  => 3,
        1000u64                 ... 9999u64                 => 4,
        10000u64                ... 99999u64                => 5,
        100000u64               ... 999999u64               => 6,
        1000000u64              ... 9999999u64              => 7,
        10000000u64             ... 99999999u64             => 8,
        100000000u64            ... 999999999u64            => 9,
        1000000000u64           ... 9999999999u64           => 10,
        10000000000u64          ... 99999999999u64          => 11,
        100000000000u64         ... 999999999999u64         => 12,
        1000000000000u64        ... 9999999999999u64        => 13,
        10000000000000u64       ... 99999999999999u64       => 14,
        100000000000000u64      ... 999999999999999u64      => 15,
        1000000000000000u64     ... 9999999999999999u64     => 16,
        10000000000000000u64    ... 99999999999999999u64    => 17,
        100000000000000000u64   ... 999999999999999999u64   => 18,
        1000000000000000000u64  ... 9999999999999999999u64  => 19,
        10000000000000000000u64 ... 18446744073709551615u64 => 20,
        _ => 0u,
    };

    if buf.len() < num_digits {
        return Err(num_digits);
    }

    for d in buf.slice_to_mut(num_digits).iter_mut().rev() {
        let rem = n % 10;
        n /= 10;
        *d = rem as u8 + b'0';
    }

    Ok(num_digits)
}

#[bench]
fn stdlib_u16_format(b: &mut test::Bencher) {
    let mut buf = [0, ..20];
    b.iter(|| {
        for i in range(0u16, 1000) {
            let mut bw = std::io::BufWriter::new(&mut buf);
            (write!(bw, "{}", i)).ok();
        }
    });
}

#[bench]
fn fast_u64_format(b: &mut test::Bencher) {
    let mut buf = [0, ..20];
    let mut dst = [0, ..20];
    b.iter(|| {
        for i in range(0u64, 1000) {
            let len = utoa(i, &mut buf).unwrap();
            let mut bw = std::io::BufWriter::new(&mut dst);
            bw.write(buf.slice_to(len)).ok();
        }
    });
}
@lifthrasiir

This comment has been minimized.

Copy link
Contributor

lifthrasiir commented Nov 23, 2014

The formatter overhead is simply too large. FWIW, I have rust-strconv to experiment with numeric conversions (for now int2dec only) and the best strategy easily overshadows the naive early-exit algorithm in use in the stdlib, but it only translates to about ~10% speedup with a formatter.

@spaolacci

This comment has been minimized.

Copy link
Contributor

spaolacci commented Feb 21, 2015

The current API also forces both ftoa/itoa to allocate their Vec<u8> outputs on each and every calls, which is a kind of perf killer. Callers should eventually be able to provide with their own large enough buffers (and strconv with a few sizing helpers).

@cmr cmr self-assigned this Mar 25, 2015

@mahkoh mahkoh closed this Apr 11, 2015

@rust-lang rust-lang locked and limited conversation to collaborators Apr 11, 2015

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.