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

Small perf improvement for fmt #57537

Merged
merged 3 commits into from
Jan 22, 2019
Merged

Small perf improvement for fmt #57537

merged 3 commits into from
Jan 22, 2019

Conversation

sinkuu
Copy link
Contributor

@sinkuu sinkuu commented Jan 12, 2019

Added benchmark is based on #10761

@rust-highfive
Copy link
Collaborator

r? @alexcrichton

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 12, 2019
@rust-highfive

This comment has been minimized.

 name                        old ns/iter  new ns/iter  diff ns/iter   diff %  speedup
 fmt::write_str_macro1       13,927       12,489             -1,438  -10.33%   x 1.12
 fmt::write_str_macro2       24,633       23,418             -1,215   -4.93%   x 1.05
 fmt::write_str_macro_debug  234,633      233,092            -1,541   -0.66%   x 1.01
 fmt::write_str_ref          5,819        5,823                   4    0.07%   x 1.00
 fmt::write_str_value        6,012        5,828                -184   -3.06%   x 1.03
 fmt::write_vec_macro1       18,550       17,143             -1,407   -7.58%   x 1.08
 fmt::write_vec_macro2       30,369       28,920             -1,449   -4.77%   x 1.05
 fmt::write_vec_macro_debug  244,338      244,901               563    0.23%   x 1.00
 fmt::write_vec_ref          5,952        5,885                 -67   -1.13%   x 1.01
 fmt::write_vec_value        5,944        5,894                 -50   -0.84%   x 1.01
name                        old2 ns/iter  new2 ns/iter  diff ns/iter   diff %  speedup
fmt::write_str_macro1       12,295        12,308                  13    0.11%   x 1.00
fmt::write_str_macro2       24,079        21,451              -2,628  -10.91%   x 1.12
fmt::write_str_macro_debug  238,363       230,807             -7,556   -3.17%   x 1.03
fmt::write_str_ref          6,203         6,064                 -139   -2.24%   x 1.02
fmt::write_str_value        6,225         6,075                 -150   -2.41%   x 1.02
fmt::write_vec_macro1       17,144        17,121                 -23   -0.13%   x 1.00
fmt::write_vec_macro2       29,845        26,703              -3,142  -10.53%   x 1.12
fmt::write_vec_macro_debug  248,840       242,117             -6,723   -2.70%   x 1.03
fmt::write_vec_ref          5,954         6,438                  484    8.13%   x 0.92
fmt::write_vec_value        5,959         6,439                  480    8.06%   x 0.93
@alexcrichton
Copy link
Member

Thanks for this! The first commit looks good to me (although somewhat requiring wizardry to fully understand, specializing iterators does make for varying performance...)

For the second commit though the code here is way out of cache for me (that optimization was added in 2014). Can you explain a bit what's going on there to help understand it?

@sinkuu
Copy link
Contributor Author

sinkuu commented Jan 14, 2019

For formats without non-default formatting params (like positions not in order ("{2} {0} {1}") or specs ("{:02X}")), Arguments::new_v1 constructor can be used instead of Arguments::new_v1_formatted. new_v1 constructs Arguments with fmt field being None, which activates the fast path in fmt::write.

This optimization should apply to "{}" (which equals to "{0}"), but there seems to be a overlook in #45807 (added ArgumentImplicitlyIs variant without updating the optimization logic).

Example

fn foo(s: &mut String) {
    // parsed as `ArgumentIs(0)`
    write!(s, "{0}", "foo");
    // parsed as `ArgumentImplicitlyIs(0)`
    write!(s, "{}", "foo");
}

Expansion before this PR:

fn foo(s: &mut String) {
    // parsed as `ArgumentIs(0)`
    s.write_fmt($crate::fmt::Arguments::new_v1(
        &[""],
        &match (&"foo",) {
            (arg0,) => [$crate::fmt::ArgumentV1::new(arg0, $crate::fmt::Display::fmt)],
        },
    ));
    // parsed as `ArgumentImplicitlyIs(0)`
    s.write_fmt($crate::fmt::Arguments::new_v1_formatted(
        &[""],
        &match (&"foo",) {
            (arg0,) => [$crate::fmt::ArgumentV1::new(arg0, $crate::fmt::Display::fmt)],
        },
        &[$crate::fmt::rt::v1::Argument {
            position: $crate::fmt::rt::v1::Position::At(0usize),
            format: $crate::fmt::rt::v1::FormatSpec {
                fill: ' ',
                align: $crate::fmt::rt::v1::Alignment::Unknown,
                flags: 0u32,
                precision: $crate::fmt::rt::v1::Count::Implied,
                width: $crate::fmt::rt::v1::Count::Implied,
            },
        }],
    ));
}

Expansion after this PR:

fn foo(s: &mut String) {
    // parsed as `ArgumentIs(0)`
    s.write_fmt($crate::fmt::Arguments::new_v1(
        &[""],
        &match (&"foo",) {
            (arg0,) => [$crate::fmt::ArgumentV1::new(arg0, $crate::fmt::Display::fmt)],
        },
    ));
    // parsed as `ArgumentImplicitlyIs(0)`
    s.write_fmt($crate::fmt::Arguments::new_v1(
        &[""],
        &match (&"foo",) {
            (arg0,) => [$crate::fmt::ArgumentV1::new(arg0, $crate::fmt::Display::fmt)],
        },
    ));
}

@alexcrichton
Copy link
Member

@bors: r+

Sounds good to me, thanks for explaining!

@bors
Copy link
Contributor

bors commented Jan 15, 2019

📌 Commit 038d837 has been approved by alexcrichton

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 15, 2019
Centril added a commit to Centril/rust that referenced this pull request Jan 15, 2019
Small perf improvement for fmt

Added benchmark is based on rust-lang#10761
Centril added a commit to Centril/rust that referenced this pull request Jan 15, 2019
Small perf improvement for fmt

Added benchmark is based on rust-lang#10761
bors added a commit that referenced this pull request Jan 15, 2019
Rollup of 7 pull requests

Successful merges:

 - #57253 (Make privacy checking, intrinsic checking and liveness checking incremental)
 - #57352 (forbid manually impl'ing one of an object type's marker traits)
 - #57537 (Small perf improvement for fmt)
 - #57579 (Add core::iter::once_with())
 - #57587 (Add 'rustc-env:RUST_BACKTRACE=0' to const-pat-ice test)
 - #57608 (Simplify 'product' factorial example)
 - #57614 ([rustdoc] Fix crates filtering box not being filled)

Failed merges:

r? @ghost
@Centril
Copy link
Contributor

Centril commented Jan 15, 2019

@bors r-

Failed in #57627 due to toolstate change (clippy).
Let's revisit this when we can make toolstate breakages again.

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jan 15, 2019
sinkuu added a commit to sinkuu/rust-clippy that referenced this pull request Jan 19, 2019
Catches up with a change in rust-lang/rust#57537

Happened to fix a bug in `expect_fun_call`, that is the lint ignores more than
one arguments to `format`.
bors added a commit to rust-lang/rust-clippy that referenced this pull request Jan 19, 2019
Catch up with `format_args` change

Catches up with a change in rust-lang/rust#57537. (Since the optimization is optional, this clippy PR can be merged before the rustc PR.)

Happened to fix a bug in `expect_fun_call`, that is the lint ignores more than
one arguments to `format`.

```
warning: use of `expect` followed by a function call
 --> src/main.rs:2:17
  |
2 |     Some("foo").expect(format!("{} {}", 1, 2).as_ref());
  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1))`
  |
```
@sinkuu
Copy link
Contributor Author

sinkuu commented Jan 22, 2019

This is ready to go. Can you re-"r+"?

@Centril
Copy link
Contributor

Centril commented Jan 22, 2019

@bors r=alexcrichton

@bors
Copy link
Contributor

bors commented Jan 22, 2019

📌 Commit 038d837 has been approved by alexcrichton

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 22, 2019
Centril added a commit to Centril/rust that referenced this pull request Jan 22, 2019
Small perf improvement for fmt

Added benchmark is based on rust-lang#10761
bors added a commit that referenced this pull request Jan 22, 2019
Rollup of 9 pull requests

Successful merges:

 - #57537 (Small perf improvement for fmt)
 - #57552 (Default images)
 - #57604 (Make `str` indexing generic on `SliceIndex`.)
 - #57667 (Fix memory leak in P::filter_map)
 - #57677 (const_eval: Predetermine the layout of all locals when pushing a stack frame)
 - #57791 (Add regression test for #54582)
 - #57798 (Corrected spelling inconsistency)
 - #57809 (Add powerpc64-unknown-freebsd)
 - #57813 (fix validation range printing when encountering undef)

Failed merges:

r? @ghost
@bors
Copy link
Contributor

bors commented Jan 22, 2019

⌛ Testing commit 038d837 with merge ad30e9a...

@bors bors merged commit 038d837 into rust-lang:master Jan 22, 2019
@sinkuu sinkuu deleted the fmt_perf branch January 23, 2019 00:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants