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

Streamline bool.TryParse/Format #64782

Merged
merged 2 commits into from
Feb 7, 2022
Merged

Conversation

stephentoub
Copy link
Member

@stephentoub stephentoub commented Feb 4, 2022

    private char[] _true = new char[] { 'T', 'r', 'u', 'e' };
    private char[] _false = new char[] { 'F', 'a', 'l', 's', 'e' };
    private char[] _somethingElse = new char[] { 'O', 't', 'h', 'e', 'r' };

    [Benchmark] public bool ParseTrue() => bool.TryParse(_true, out _);
    [Benchmark] public bool ParseFalse() => bool.TryParse(_false, out _);
    [Benchmark] public bool ParseSomethingElse() => bool.TryParse(_somethingElse, out _);

    [Benchmark] public bool FormatTrue() => true.TryFormat(_true, out _);
    [Benchmark] public bool FormatFalse() => false.TryFormat(_false, out _);
Method Toolchain Mean Error StdDev Ratio
ParseTrue \main\corerun.exe 7.311 ns 0.0171 ns 0.0142 ns 1.00
ParseTrue \pr\corerun.exe 1.149 ns 0.0243 ns 0.0203 ns 0.16
ParseFalse \main\corerun.exe 8.749 ns 0.0569 ns 0.0504 ns 1.00
ParseFalse \pr\corerun.exe 2.309 ns 0.0572 ns 0.0477 ns 0.26
ParseSomethingElse \main\corerun.exe 17.638 ns 0.1478 ns 0.1382 ns 1.00
ParseSomethingElse \pr\corerun.exe 8.219 ns 0.0511 ns 0.0453 ns 0.47
FormatTrue \main\corerun.exe 3.117 ns 0.0245 ns 0.0204 ns 1.00
FormatTrue \pr\corerun.exe 2.000 ns 0.0287 ns 0.0269 ns 0.64
FormatFalse \main\corerun.exe 2.101 ns 0.0363 ns 0.0322 ns 1.00
FormatFalse \pr\corerun.exe 2.065 ns 0.0416 ns 0.0389 ns 0.98

@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label.

@ghost
Copy link

ghost commented Feb 4, 2022

Tagging subscribers to this area: @dotnet/area-system-runtime
See info in area-owners.md if you want to be subscribed.

Issue Details
    private char[] _true = new char[] { 'T', 'r', 'u', 'e' };
    private char[] _false = new char[] { 'F', 'a', 'l', 's', 'e' };
    private char[] _somethingElse = new char[] { 'O', 't', 'h', 'e', 'r' };

    [Benchmark] public bool ParseTrue() => bool.TryParse(_true, out _);
    [Benchmark] public bool ParseFalse() => bool.TryParse(_false, out _);
    [Benchmark] public bool ParseSomethingElse() => bool.TryParse(_somethingElse, out _);

    [Benchmark] public bool FormatTrue() => true.TryFormat(_true, out _);
    [Benchmark] public bool FormatFalse() => false.TryFormat(_false, out _);
Method Toolchain Mean Error StdDev Ratio
ParseTrue \main\corerun.exe 7.311 ns 0.0171 ns 0.0142 ns 1.00
ParseTrue \pr\corerun.exe 1.149 ns 0.0243 ns 0.0203 ns 0.16
ParseFalse \main\corerun.exe 8.749 ns 0.0569 ns 0.0504 ns 1.00
ParseFalse \pr\corerun.exe 2.309 ns 0.0572 ns 0.0477 ns 0.26
ParseSomethingElse \main\corerun.exe 17.638 ns 0.1478 ns 0.1382 ns 1.00
ParseSomethingElse \pr\corerun.exe 8.219 ns 0.0511 ns 0.0453 ns 0.47
FormatTrue \main\corerun.exe 3.117 ns 0.0245 ns 0.0204 ns 1.00
FormatTrue \pr\corerun.exe 2.000 ns 0.0287 ns 0.0269 ns 0.64
FormatFalse \main\corerun.exe 2.101 ns 0.0363 ns 0.0322 ns 1.00
FormatFalse \pr\corerun.exe 2.065 ns 0.0416 ns 0.0389 ns 0.98
Author: stephentoub
Assignees: stephentoub
Labels:

area-System.Runtime

Milestone: -

@danmoseley
Copy link
Member

Do you think that TrimWhiteSpaceAndNull can be improved also? It's on the "not a boolean" path.

@stephentoub
Copy link
Member Author

Do you think that TrimWhiteSpaceAndNull can be improved also?

I don't see anything about the implementation that can be meaningfully improved without restoring to unsafe code, at least not until the JIT recognizes some sort of backward iteration pattern for bounds-check elimination.

We can, however, push that whole trimming path off into a separate function, making it a bit cheaper to invoke the main parsing routine, along with being able to add a few more checks to more quickly weed out bad inputs.

Method Toolchain value Mean Error Ratio
TryParse \main\corerun.exe True 18.4991 ns 0.0338 ns 1.00
TryParse \pr\corerun.exe True 9.2014 ns 0.0485 ns 0.50
TryParse \main\corerun.exe 0 15.6529 ns 0.0662 ns 1.00
TryParse \pr\corerun.exe 0 1.2378 ns 0.0064 ns 0.08
TryParse \main\corerun.exe Bogus 17.7503 ns 0.0832 ns 1.00
TryParse \pr\corerun.exe Bogus 6.8170 ns 0.0342 ns 0.38
TryParse \main\corerun.exe False 7.8471 ns 0.0274 ns 1.00
TryParse \pr\corerun.exe False 1.4798 ns 0.0066 ns 0.19
TryParse \main\corerun.exe TRUE 8.1593 ns 0.0226 ns 1.00
TryParse \pr\corerun.exe TRUE 0.8097 ns 0.0060 ns 0.10
TryParse \main\corerun.exe false 7.9468 ns 0.0555 ns 1.00
TryParse \pr\corerun.exe false 1.4835 ns 0.0090 ns 0.19
TryParse \main\corerun.exe true 7.1882 ns 0.0645 ns 1.00
TryParse \pr\corerun.exe true 0.8110 ns 0.0068 ns 0.11

@danmoseley
Copy link
Member

Assuming that once we get to trimming the result will usually be a failure, I wonder whether IndexOfAny(char[] { 'e', 'E' } might allow bailing out quickly if the input is large.

@stephentoub
Copy link
Member Author

Assuming that once we get to trimming the result will usually be a failure, I wonder whether IndexOfAny(char[] { 'e', 'E' } might allow bailing out quickly if the input is large.

Have you seen any real-world cases of large inputs filled with whitespace and nulls being passed to bool.{Try}Parse?

@uweigand
Copy link
Contributor

uweigand commented Feb 9, 2022

This commit introduced serious regressions on s390x, about 40 library test cases now fail.

The problem seems to be that this (and similar lines):

BinaryPrimitives.WriteUInt64LittleEndian(MemoryMarshal.AsBytes(destination), 0x65007500720054); // "True"

is incorrect on big-endian systems. The destination memory will be set up as the following bytes:

 54 00 72 00 75 00 65 00

while on a big-endian system, the string should actually be:

 00 54 00 72 00 75 00 65

I'm currently testing a fix.

@uweigand
Copy link
Contributor

uweigand commented Feb 9, 2022

I'm currently testing a fix.

This is now #65078

@EgorBo
Copy link
Member

EgorBo commented Feb 15, 2022

Improvements: dotnet/perf-autofiling-issues#3529

@stephentoub
Copy link
Member Author

Improvements

Always nice when what you saw locally is mirrored by the lab subsequently :)

@ghost ghost locked as resolved and limited conversation to collaborators Mar 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants