Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Perf improvements to char.IsWhiteSpace / char.IsUpper / char.IsLower - #26848

Merged
GrabYourPitchforks merged 3 commits into
dotnet:masterfrom
GrabYourPitchforks:char_updates
Sep 24, 2019
Merged

GrabYourPitchforks merged 3 commits into
dotnet:masterfrom
GrabYourPitchforks:char_updates

Conversation

@GrabYourPitchforks

Copy link
Copy Markdown
Member

This is especially noticeable in benchmarks for APIs like ReadOnlySpan.Trim().

Method Toolchain input Mean Error StdDev Median Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated
Trim master {empty} 3.509 ns 0.0475 ns 0.0444 ns 3.501 ns 1.00 0.00 - - - -
Trim proto {empty} 3.423 ns 0.0801 ns 0.0710 ns 3.399 ns 0.98 0.03 - - - -
Trim master {spaces on both sides} 9.161 ns 0.2052 ns 0.2195 ns 9.091 ns 1.00 0.00 - - - -
Trim proto {spaces on both sides} 7.299 ns 0.1714 ns 0.1519 ns 7.287 ns 0.79 0.02 - - - -
CountLowerChars master Hello(...)able! [23] 55.934 ns 0.8882 ns 0.8308 ns 55.705 ns 1.00 0.00 - - - -
CountLowerChars proto Hello(...)able! [23] 47.130 ns 0.4410 ns 0.4125 ns 47.166 ns 0.84 0.01 - - - -
CountUpperChars master Hello(...)able! [23] 61.556 ns 0.6651 ns 0.5554 ns 61.641 ns 1.00 0.00 - - - -
CountUpperChars proto Hello(...)able! [23] 53.805 ns 0.3064 ns 0.2717 ns 53.747 ns 0.87 0.01 - - - -
Trim master abcdefg 5.753 ns 0.0402 ns 0.0376 ns 5.753 ns 1.00 0.00 - - - -
Trim proto abcdefg 5.249 ns 0.1380 ns 0.2970 ns 5.137 ns 0.97 0.05 - - - -

Benchmark code:

[Benchmark]
[ArgumentsSource(nameof(TrimArguments))]
public ReadOnlySpan<char> Trim(string input) => input.AsSpan().Trim();

[Benchmark]
[Arguments("Hello there, Constable!")]
public int CountLowerChars(string input)
{
    int count = 0;

    foreach (char ch in input)
    {
        if (char.IsLower(ch)) { count++; }
    }

    return count;
}

[Benchmark]
[Arguments("Hello there, Constable!")]
public int CountUpperChars(string input)
{
    int count = 0;

    foreach (char ch in input)
    {
        if (char.IsUpper(ch)) { count++; }
    }

    return count;
}

public static IEnumerable<object> TrimArguments()
{
    yield return "";
    yield return " abcdefg ";
    yield return "abcdefg";
}

The performance should improve even further when https://github.com/dotnet/coreclr/issues/26845 is fixed.

@EgorBo

EgorBo commented Sep 23, 2019

Copy link
Copy Markdown
Member

This PR also was supposed to remove CategoryForLatin1 bound checks: #25912

@GrabYourPitchforks

Copy link
Copy Markdown
Member Author

Unit tests at dotnet/corefx#41265.

Comment thread src/System.Private.CoreLib/shared/System/Char.cs
Comment thread src/System.Private.CoreLib/shared/System/Char.cs
Comment thread src/System.Private.CoreLib/shared/System/Char.cs

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment thread src/System.Private.CoreLib/shared/System/Char.cs
No functional changes
@GrabYourPitchforks

Copy link
Copy Markdown
Member Author

CI failures are unrelated. Marching forward with submission.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants