Skip to content

Integer to_string is slow #135543

New issue

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

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

Already on GitHub? # to your account

Open
jh05013 opened this issue Jan 15, 2025 · 4 comments
Open

Integer to_string is slow #135543

jh05013 opened this issue Jan 15, 2025 · 4 comments
Labels
A-fmt Area: `core::fmt` C-optimization Category: An issue highlighting optimization opportunities or PRs implementing such

Comments

@jh05013
Copy link

jh05013 commented Jan 15, 2025

On my machine, the following code runs in 3 seconds in stable version, release build:

// (EDIT: made it compile)
fn main() {
    for i in 0..100000000u32 {
        let s = i.to_string();
        assert!(s.len() > 0);
    }
}

whereas the C++ counterpart runs in 1.2 seconds with -O2:

#include <string>
#include <cassert>
int main() {
    for(unsigned int i=0; i<100000000; i++){
        std::string s = std::to_string(i);
        assert(s.size() > 0);
    }
}

I've found that most of the time loss comes from passing &str through a formatter instead of directly memcpying; replacing to_string with _fmt with .to_owned() at the end speeds it up to around 1.6s.

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jan 15, 2025
@clubby789 clubby789 added C-optimization Category: An issue highlighting optimization opportunities or PRs implementing such and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jan 15, 2025
@clubby789
Copy link
Contributor

FWIW, my understanding is that formatting goes through dynamic dispatch, as a deliberate choice to reduce the binary size bloat from inlining all formatting

@workingjubilee

This comment has been minimized.

@jfrimmel
Copy link
Contributor

You can try the itoa-crate, which removes some overhead mentioned in the first comment.

@GuillaumeGomez
Copy link
Member

To be noted that there is work in progress to improve this situation. Already two PRs were merged:

Hopefully more will follow soon. :)

@lolbinarycat lolbinarycat added the A-fmt Area: `core::fmt` label Jan 18, 2025
bors added a commit to rust-lang-ci/rust that referenced this issue Jan 30, 2025
…string, r=<try>

Optimize `ToString` implementation for integers

Part of rust-lang#135543.

Follow-up of rust-lang#133247 and rust-lang#128204.

Rather than writing pretty bad benchers like I did last time, `@workingjubilee:` do you have a suggestion on how to check the impact on performance for this PR? Thanks in advance!

r? `@workingjubilee`
bors added a commit to rust-lang-ci/rust that referenced this issue May 13, 2025
…string, r=Amanieu

Optimize `ToString` implementation for integers

Part of rust-lang#135543.

Follow-up of rust-lang#133247 and rust-lang#128204.

The benchmark results are:

| name| 1.87.0-nightly (3ea711f 2025-03-09) | With this PR | diff |
|-|-|-|-|
| bench_i16 | 32.06 ns/iter (+/- 0.12) | 17.62 ns/iter (+/- 0.03) | -45% |
| bench_i32 | 31.61 ns/iter (+/- 0.04) | 15.10 ns/iter (+/- 0.06) | -52% |
| bench_i64 | 31.71 ns/iter (+/- 0.07) | 15.02 ns/iter (+/- 0.20) | -52% |
| bench_i8 | 13.21 ns/iter (+/- 0.14) | 14.93 ns/iter (+/- 0.16) | +13% |
| bench_u16 | 31.20 ns/iter (+/- 0.06) | 16.14 ns/iter (+/- 0.11) | -48% |
| bench_u32 | 33.27 ns/iter (+/- 0.05) | 16.18 ns/iter (+/- 0.10) | -51% |
| bench_u64 | 31.44 ns/iter (+/- 0.06) | 16.62 ns/iter (+/- 0.21) | -47% |
| bench_u8 | 10.57 ns/iter (+/- 0.30) | 13.00 ns/iter (+/- 0.43) | +22% |

More information about it in [the original comment](rust-lang#136264 (comment)).

r? `@workingjubilee`
bors added a commit to rust-lang-ci/rust that referenced this issue May 13, 2025
…string, r=Amanieu

Optimize `ToString` implementation for integers

Part of rust-lang#135543.

Follow-up of rust-lang#133247 and rust-lang#128204.

The benchmark results are:

| name| 1.87.0-nightly (3ea711f 2025-03-09) | With this PR | diff |
|-|-|-|-|
| bench_i16 | 32.06 ns/iter (+/- 0.12) | 17.62 ns/iter (+/- 0.03) | -45% |
| bench_i32 | 31.61 ns/iter (+/- 0.04) | 15.10 ns/iter (+/- 0.06) | -52% |
| bench_i64 | 31.71 ns/iter (+/- 0.07) | 15.02 ns/iter (+/- 0.20) | -52% |
| bench_i8 | 13.21 ns/iter (+/- 0.14) | 14.93 ns/iter (+/- 0.16) | +13% |
| bench_u16 | 31.20 ns/iter (+/- 0.06) | 16.14 ns/iter (+/- 0.11) | -48% |
| bench_u32 | 33.27 ns/iter (+/- 0.05) | 16.18 ns/iter (+/- 0.10) | -51% |
| bench_u64 | 31.44 ns/iter (+/- 0.06) | 16.62 ns/iter (+/- 0.21) | -47% |
| bench_u8 | 10.57 ns/iter (+/- 0.30) | 13.00 ns/iter (+/- 0.43) | +22% |

More information about it in [the original comment](rust-lang#136264 (comment)).

r? `@workingjubilee`
bors added a commit to rust-lang-ci/rust that referenced this issue May 14, 2025
…string, r=<try>

Optimize `ToString` implementation for integers

Part of rust-lang#135543.

Follow-up of rust-lang#133247 and rust-lang#128204.

The benchmark results are:

| name| 1.87.0-nightly (3ea711f 2025-03-09) | With this PR | diff |
|-|-|-|-|
| bench_i16 | 32.06 ns/iter (+/- 0.12) | 17.62 ns/iter (+/- 0.03) | -45% |
| bench_i32 | 31.61 ns/iter (+/- 0.04) | 15.10 ns/iter (+/- 0.06) | -52% |
| bench_i64 | 31.71 ns/iter (+/- 0.07) | 15.02 ns/iter (+/- 0.20) | -52% |
| bench_i8 | 13.21 ns/iter (+/- 0.14) | 14.93 ns/iter (+/- 0.16) | +13% |
| bench_u16 | 31.20 ns/iter (+/- 0.06) | 16.14 ns/iter (+/- 0.11) | -48% |
| bench_u32 | 33.27 ns/iter (+/- 0.05) | 16.18 ns/iter (+/- 0.10) | -51% |
| bench_u64 | 31.44 ns/iter (+/- 0.06) | 16.62 ns/iter (+/- 0.21) | -47% |
| bench_u8 | 10.57 ns/iter (+/- 0.30) | 13.00 ns/iter (+/- 0.43) | +22% |

More information about it in [the original comment](rust-lang#136264 (comment)).

r? `@workingjubilee`
bors added a commit to rust-lang-ci/rust that referenced this issue May 14, 2025
…string, r=Amanieu

Optimize `ToString` implementation for integers

Part of rust-lang#135543.

Follow-up of rust-lang#133247 and rust-lang#128204.

The benchmark results are:

| name| 1.87.0-nightly (3ea711f 2025-03-09) | With this PR | diff |
|-|-|-|-|
| bench_i16 | 32.06 ns/iter (+/- 0.12) | 17.62 ns/iter (+/- 0.03) | -45% |
| bench_i32 | 31.61 ns/iter (+/- 0.04) | 15.10 ns/iter (+/- 0.06) | -52% |
| bench_i64 | 31.71 ns/iter (+/- 0.07) | 15.02 ns/iter (+/- 0.20) | -52% |
| bench_i8 | 13.21 ns/iter (+/- 0.14) | 14.93 ns/iter (+/- 0.16) | +13% |
| bench_u16 | 31.20 ns/iter (+/- 0.06) | 16.14 ns/iter (+/- 0.11) | -48% |
| bench_u32 | 33.27 ns/iter (+/- 0.05) | 16.18 ns/iter (+/- 0.10) | -51% |
| bench_u64 | 31.44 ns/iter (+/- 0.06) | 16.62 ns/iter (+/- 0.21) | -47% |
| bench_u8 | 10.57 ns/iter (+/- 0.30) | 13.00 ns/iter (+/- 0.43) | +22% |

More information about it in [the original comment](rust-lang#136264 (comment)).

r? `@workingjubilee`
bors added a commit to rust-lang-ci/rust that referenced this issue May 15, 2025
…string, r=Amanieu

Optimize `ToString` implementation for integers

Part of rust-lang#135543.

Follow-up of rust-lang#133247 and rust-lang#128204.

The benchmark results are:

| name| 1.87.0-nightly (3ea711f 2025-03-09) | With this PR | diff |
|-|-|-|-|
| bench_i16 | 32.06 ns/iter (+/- 0.12) | 17.62 ns/iter (+/- 0.03) | -45% |
| bench_i32 | 31.61 ns/iter (+/- 0.04) | 15.10 ns/iter (+/- 0.06) | -52% |
| bench_i64 | 31.71 ns/iter (+/- 0.07) | 15.02 ns/iter (+/- 0.20) | -52% |
| bench_i8 | 13.21 ns/iter (+/- 0.14) | 14.93 ns/iter (+/- 0.16) | +13% |
| bench_u16 | 31.20 ns/iter (+/- 0.06) | 16.14 ns/iter (+/- 0.11) | -48% |
| bench_u32 | 33.27 ns/iter (+/- 0.05) | 16.18 ns/iter (+/- 0.10) | -51% |
| bench_u64 | 31.44 ns/iter (+/- 0.06) | 16.62 ns/iter (+/- 0.21) | -47% |
| bench_u8 | 10.57 ns/iter (+/- 0.30) | 13.00 ns/iter (+/- 0.43) | +22% |

More information about it in [the original comment](rust-lang#136264 (comment)).

r? `@workingjubilee`
github-merge-queue bot pushed a commit to rust-lang/miri that referenced this issue May 17, 2025
…=Amanieu

Optimize `ToString` implementation for integers

Part of rust-lang/rust#135543.

Follow-up of rust-lang/rust#133247 and rust-lang/rust#128204.

The benchmark results are:

| name| 1.87.0-nightly (3ea711f17 2025-03-09) | With this PR | diff |
|-|-|-|-|
| bench_i16 | 32.06 ns/iter (+/- 0.12) | 17.62 ns/iter (+/- 0.03) | -45% |
| bench_i32 | 31.61 ns/iter (+/- 0.04) | 15.10 ns/iter (+/- 0.06) | -52% |
| bench_i64 | 31.71 ns/iter (+/- 0.07) | 15.02 ns/iter (+/- 0.20) | -52% |
| bench_i8 | 13.21 ns/iter (+/- 0.14) | 14.93 ns/iter (+/- 0.16) | +13% |
| bench_u16 | 31.20 ns/iter (+/- 0.06) | 16.14 ns/iter (+/- 0.11) | -48% |
| bench_u32 | 33.27 ns/iter (+/- 0.05) | 16.18 ns/iter (+/- 0.10) | -51% |
| bench_u64 | 31.44 ns/iter (+/- 0.06) | 16.62 ns/iter (+/- 0.21) | -47% |
| bench_u8 | 10.57 ns/iter (+/- 0.30) | 13.00 ns/iter (+/- 0.43) | +22% |

More information about it in [the original comment](rust-lang/rust#136264 (comment)).

r? `@workingjubilee`
github-actions bot pushed a commit to rust-lang/rustc-dev-guide that referenced this issue May 19, 2025
…=Amanieu

Optimize `ToString` implementation for integers

Part of rust-lang/rust#135543.

Follow-up of rust-lang/rust#133247 and rust-lang/rust#128204.

The benchmark results are:

| name| 1.87.0-nightly (3ea711f17 2025-03-09) | With this PR | diff |
|-|-|-|-|
| bench_i16 | 32.06 ns/iter (+/- 0.12) | 17.62 ns/iter (+/- 0.03) | -45% |
| bench_i32 | 31.61 ns/iter (+/- 0.04) | 15.10 ns/iter (+/- 0.06) | -52% |
| bench_i64 | 31.71 ns/iter (+/- 0.07) | 15.02 ns/iter (+/- 0.20) | -52% |
| bench_i8 | 13.21 ns/iter (+/- 0.14) | 14.93 ns/iter (+/- 0.16) | +13% |
| bench_u16 | 31.20 ns/iter (+/- 0.06) | 16.14 ns/iter (+/- 0.11) | -48% |
| bench_u32 | 33.27 ns/iter (+/- 0.05) | 16.18 ns/iter (+/- 0.10) | -51% |
| bench_u64 | 31.44 ns/iter (+/- 0.06) | 16.62 ns/iter (+/- 0.21) | -47% |
| bench_u8 | 10.57 ns/iter (+/- 0.30) | 13.00 ns/iter (+/- 0.43) | +22% |

More information about it in [the original comment](rust-lang/rust#136264 (comment)).

r? `@workingjubilee`
lnicola pushed a commit to lnicola/rust-analyzer that referenced this issue May 20, 2025
…=Amanieu

Optimize `ToString` implementation for integers

Part of rust-lang/rust#135543.

Follow-up of rust-lang/rust#133247 and rust-lang/rust#128204.

The benchmark results are:

| name| 1.87.0-nightly (3ea711f17 2025-03-09) | With this PR | diff |
|-|-|-|-|
| bench_i16 | 32.06 ns/iter (+/- 0.12) | 17.62 ns/iter (+/- 0.03) | -45% |
| bench_i32 | 31.61 ns/iter (+/- 0.04) | 15.10 ns/iter (+/- 0.06) | -52% |
| bench_i64 | 31.71 ns/iter (+/- 0.07) | 15.02 ns/iter (+/- 0.20) | -52% |
| bench_i8 | 13.21 ns/iter (+/- 0.14) | 14.93 ns/iter (+/- 0.16) | +13% |
| bench_u16 | 31.20 ns/iter (+/- 0.06) | 16.14 ns/iter (+/- 0.11) | -48% |
| bench_u32 | 33.27 ns/iter (+/- 0.05) | 16.18 ns/iter (+/- 0.10) | -51% |
| bench_u64 | 31.44 ns/iter (+/- 0.06) | 16.62 ns/iter (+/- 0.21) | -47% |
| bench_u8 | 10.57 ns/iter (+/- 0.30) | 13.00 ns/iter (+/- 0.43) | +22% |

More information about it in [the original comment](rust-lang/rust#136264 (comment)).

r? `@workingjubilee`
github-actions bot pushed a commit to model-checking/verify-rust-std that referenced this issue May 21, 2025
…string, r=Amanieu

Optimize `ToString` implementation for integers

Part of rust-lang#135543.

Follow-up of rust-lang#133247 and rust-lang#128204.

The benchmark results are:

| name| 1.87.0-nightly (3ea711f 2025-03-09) | With this PR | diff |
|-|-|-|-|
| bench_i16 | 32.06 ns/iter (+/- 0.12) | 17.62 ns/iter (+/- 0.03) | -45% |
| bench_i32 | 31.61 ns/iter (+/- 0.04) | 15.10 ns/iter (+/- 0.06) | -52% |
| bench_i64 | 31.71 ns/iter (+/- 0.07) | 15.02 ns/iter (+/- 0.20) | -52% |
| bench_i8 | 13.21 ns/iter (+/- 0.14) | 14.93 ns/iter (+/- 0.16) | +13% |
| bench_u16 | 31.20 ns/iter (+/- 0.06) | 16.14 ns/iter (+/- 0.11) | -48% |
| bench_u32 | 33.27 ns/iter (+/- 0.05) | 16.18 ns/iter (+/- 0.10) | -51% |
| bench_u64 | 31.44 ns/iter (+/- 0.06) | 16.62 ns/iter (+/- 0.21) | -47% |
| bench_u8 | 10.57 ns/iter (+/- 0.30) | 13.00 ns/iter (+/- 0.43) | +22% |

More information about it in [the original comment](rust-lang#136264 (comment)).

r? `@workingjubilee`
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-fmt Area: `core::fmt` C-optimization Category: An issue highlighting optimization opportunities or PRs implementing such
Projects
None yet
Development

No branches or pull requests

7 participants