Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Improve perf of Utf8Parser.TryParse for int64 and uint64#52423

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

@GrabYourPitchforks
Copy link
Member

@GrabYourPitchforksGrabYourPitchforks commentedMay 7, 2021
edited
Loading

Somewhat inspired by investigating#52314 and seeing a little bit of low-hanging fruit that we can address.

Perf results (basically from runningthis benchmark with some additional inputs):

MethodToolchainvalueMeanErrorStdDevRatio
TryParseInt64baseline-13.73 ns0.022 ns0.018 ns1.00
TryParseInt64compare-13.25 ns0.025 ns0.021 ns0.87
TryParseInt64baseline-123455.93 ns1.680 ns0.092 ns1.00
TryParseInt64compare-123455.85 ns1.097 ns0.060 ns0.99
TryParseInt64baseline-1234567890123456715.75 ns43.214 ns2.368 ns1.00
TryParseInt64compare-1234567890123456713.24 ns0.371 ns0.020 ns0.85
TryParseInt64baseline-922337203685477580819.35 ns0.326 ns0.305 ns1.00
TryParseInt64compare-922337203685477580817.12 ns0.085 ns0.076 ns0.88
TryParseInt64baseline03.17 ns0.097 ns0.005 ns1.00
TryParseInt64compare03.21 ns0.602 ns0.033 ns1.01
TryParseInt64baseline13.27 ns0.060 ns0.003 ns1.00
TryParseInt64compare13.21 ns0.322 ns0.017 ns0.98
TryParseInt64baseline123455.76 ns0.738 ns0.040 ns1.00
TryParseInt64compare123455.07 ns0.929 ns0.050 ns0.88
TryParseInt64baseline1234567890123456713.90 ns0.247 ns0.013 ns1.00
TryParseInt64compare1234567890123456712.85 ns1.504 ns0.082 ns0.92
TryParseInt64baseline922337203685477580717.72 ns0.102 ns0.095 ns1.00
TryParseInt64compare922337203685477580716.11 ns0.063 ns0.059 ns0.91

Some of the benchmarks were going a bit screwy on my machine, so I basically ran them one at a time and concatenated all of the results into a single table. Not sure what was up with my environment.

The tl;dr is that this shouldn't have any worse perf than the existing code, and the total codegen ends up being448 bytes smaller (on x64) compared to baseline across the two methods.

@ghost
Copy link

Tagging subscribers to this area:@tannergooding,@pgovind,@GrabYourPitchforks
See info inarea-owners.md if you want to be subscribed.

Issue Details

Somewhat inspired by investigating#52314 and seeing a little bit of low-hanging fruit that we can address.

Perf results (basically from runningthis benchmark with some additional inputs):

| Method | Toolchain | value | Mean Error | StdDev | Ratio |
|-------------- |---------- |--------------------- |---------:|----------:|---------:|------:|
| TryParseInt64 | baseline | -1 | 3.73 ns | 0.022 ns | 0.018 ns | 1.00 |
| TryParseInt64 | compare | -1 | 3.25 ns | 0.025 ns | 0.021 ns | 0.87 |
| | | | | | | |
| TryParseInt64 | baseline | -12345 | 5.93 ns | 1.680 ns | 0.092 ns | 1.00 |
| TryParseInt64 | compare | -12345 | 5.85 ns | 1.097 ns | 0.060 ns | 0.99 |
| | | | | | | |
| TryParseInt64 | baseline | -12345678901234567 | 15.75 ns | 43.214 ns | 2.368 ns | 1.00 |
| TryParseInt64 | compare | -12345678901234567 | 13.24 ns | 0.371 ns | 0.020 ns | 0.85 |
| | | | | | | |
| TryParseInt64 | baseline | -9223372036854775808 | 19.35 ns | 0.326 ns | 0.305 ns | 1.00 |
| TryParseInt64 | compare | -9223372036854775808 | 17.12 ns | 0.085 ns | 0.076 ns | 0.88 |
| | | | | | | |
| TryParseInt64 | baseline | 0 | 3.17 ns | 0.097 ns | 0.005 ns | 1.00 |
| TryParseInt64 | compare | 0 | 3.21 ns | 0.602 ns | 0.033 ns | 1.01 |
| | | | | | | |
| TryParseInt64 | baseline | 1 | 3.27 ns | 0.060 ns | 0.003 ns | 1.00 |
| TryParseInt64 | compare | 1 | 3.21 ns | 0.322 ns | 0.017 ns | 0.98 |
| | | | | | | |
| TryParseInt64 | baseline | 12345 | 5.76 ns | 0.738 ns | 0.040 ns | 1.00 |
| TryParseInt64 | compare | 12345 | 5.07 ns | 0.929 ns | 0.050 ns | 0.88 |
| | | | | | | |
| TryParseInt64 | baseline | 12345678901234567 | 13.90 ns | 0.247 ns | 0.013 ns | 1.00 |
| TryParseInt64 | compare | 12345678901234567 | 12.85 ns | 1.504 ns | 0.082 ns | 0.92 |
| | | | | | | |
| TryParseInt64 | baseline | 9223372036854775807 | 17.72 ns | 0.102 ns | 0.095 ns | 1.00 |
| TryParseInt64 | compare | 9223372036854775807 | 16.11 ns | 0.063 ns | 0.059 ns | 0.91 |

Some of the benchmarks were going a bit screwy on my machine, so I basically ran them one at a time and concatenated all of the results into a single table. Not sure what was up with my environment.

The tl;dr is that this shouldn't have any worse perf than the existing code, and the total codegen ends up being448 bytes smaller compared to baseline across the two methods.

Author:GrabYourPitchforks
Assignees:-
Labels:

area-System.Buffers,tenet-performance

Milestone:6.0.0


if((uint)firstChar==unchecked((uint)('-'-'0')))
{
sign--;// set to -1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
sign--;// set to -1
sign=-1;

Make it explicit?
The JIT will emit code likemov rax, 0xffffffffffffffff anyway.

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The JIT emitsdec rax for this scenario. I think it doesn't propagate the "if (idx != 0) { FAIL; }" assertion above for some reason.
I can setsign = -1; explicitly, but it does increase the codegen by 7 - 8 bytes. Maybe it's too much of a microoptimization to worry about and the cleaner code is better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

So I'd keep it as is. Thanks for the info.

// If sign = -1, this becomes value = (parsedValue ^ -1) - (-1) = ~parsedValue + 1 = -parsedValue

bytesConsumed=idx;
value=((long)parsedValue^sign)-sign;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

🚀

The same could be done to other types too (like int32 above, etc.)?

Copy link
Member

@stephentoubstephentoub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thanks. Are there any similar gains to be had in {u}long.TryParse?

@jeffhandley
Copy link
Member

@GrabYourPitchforks Is this ready to merge?

@jeffhandley
Copy link
Member

@GrabYourPitchforks Is this ready to merge?

Ping on this,@GrabYourPitchforks. It would be great to get this in for Preview 7.

@GrabYourPitchforks
Copy link
MemberAuthor

I investigated the framework's other parsing routines, but they have a bit more complexity, needing to handle whitespace and trailing nulls. Opened#55541 so we don't lose track of this.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@stephentoubstephentoubstephentoub approved these changes

@adamsitnikadamsitnikAwaiting requested review from adamsitnik

@pgovindpgovindAwaiting requested review from pgovind

@tannergoodingtannergoodingAwaiting requested review from tannergooding

+1 more reviewer

@gfoidlgfoidlgfoidl left review comments

Reviewers whose approvals may not affect merge requirements

Labels

area-System.Bufferstenet-performancePerformance related issue

Projects

None yet

Milestone

6.0.0

Development

Successfully merging this pull request may close these issues.

4 participants

@GrabYourPitchforks@jeffhandley@stephentoub@gfoidl

[8]ページ先頭

©2009-2025 Movatter.jp