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

[core] use StringComparison.Ordinal everywhere #4988

Merged

Conversation

jonathanpeppers
Copy link
Member

Context: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1307
Context: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1309
Context: dotnet/runtime#43956

I was reviewing dotnet trace output of the .NET Podcast app:

6.32ms Microsoft.Maui.Controls!Microsoft.Maui.Controls.ShellNavigationManager.GetNavigationState
3.82ms Microsoft.Maui.Controls!Microsoft.Maui.Controls.ShellUriHandler.FormatUri

The bulk of this time is spent in string.StartsWith(), doing a
culture-aware string comparison?

3.82ms System.Private.CoreLib!System.String.StartsWith
2.57ms System.Private.CoreLib!System.Globalization.CultureInfo.get_CurrentCulture

This looks to be showing the cost of the 1st culture-aware comparision
plus any time making these slower string comparisons. It would be
ideal if project templates did not even hit
CultureInfo.get_CurrentCulture.

To solve this, let's add to the .editorconfig file:

dotnet_diagnostic.CA1307.severity = error
dotnet_diagnostic.CA1309.severity = error

And then fix all the places errors appear.

There are some complications in projects that use netstandard2.0:

  1. For Contains() use IndexOf() instead.

  2. Use #if NETSTANDARD2_0 for GetHashCode() or Replace().

  3. Generally, InvariantCulture should not be used.

After these changes, the FormatUri method disappears completely from
the trace, and we instead get:

2.88ms Microsoft.Maui.Controls!Microsoft.Maui.Controls.ShellNavigationManager.GetNavigationState

I suspect this saves ~3.44ms for any MAUI app startup, and a small
amount more depending on the number of string comparisions happening.

@jsuarezruiz jsuarezruiz added the legacy-area-perf Startup / Runtime performance label Mar 1, 2022
@jonathanpeppers jonathanpeppers force-pushed the StringComparisonOrdinal branch 4 times, most recently from 90c46f7 to e11fe7d Compare March 1, 2022 17:44
@jonathanpeppers
Copy link
Member Author

The rules in the .editorconfig keep finding more of these. Almost got them all...

@jonathanpeppers jonathanpeppers force-pushed the StringComparisonOrdinal branch 2 times, most recently from bf94fa4 to f2f04bc Compare March 1, 2022 21:02
@jonathanpeppers jonathanpeppers marked this pull request as ready for review March 1, 2022 21:44
@jonathanpeppers jonathanpeppers requested a review from a team as a code owner March 1, 2022 21:44
Copy link
Contributor

@pranavkm pranavkm left a comment

Choose a reason for hiding this comment

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

A couple of places it looks like it's attempting to StringComparison for char comparisons.

Context: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1307
Context: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1309
Context: dotnet/runtime#43956

I was reviewing `dotnet trace` output of the .NET Podcast app:

    6.32ms Microsoft.Maui.Controls!Microsoft.Maui.Controls.ShellNavigationManager.GetNavigationState
    3.82ms Microsoft.Maui.Controls!Microsoft.Maui.Controls.ShellUriHandler.FormatUri

The bulk of this time is spent in `string.StartsWith()`, doing a
culture-aware string comparison?

    3.82ms System.Private.CoreLib!System.String.StartsWith
    2.57ms System.Private.CoreLib!System.Globalization.CultureInfo.get_CurrentCulture

This looks to be showing the cost of the 1st culture-aware comparision
plus any time making these slower string comparisons. It would be
ideal if project templates did not even hit
`CultureInfo.get_CurrentCulture`.

To solve this, let's add to the `.editorconfig` file:

    dotnet_diagnostic.CA1307.severity = error
    dotnet_diagnostic.CA1309.severity = error

And then fix all the places errors appear.

There are some complications in projects that use `netstandard2.0`:

1. For `Contains()` use `IndexOf()` instead.

2. Use `#if NETSTANDARD2_0` for `GetHashCode()` or `Replace()`.

3. Generally, `InvariantCulture` should not be used.

After these changes, the `FormatUri` method disappears completely from
the trace, and we instead get:

    2.88ms Microsoft.Maui.Controls!Microsoft.Maui.Controls.ShellNavigationManager.GetNavigationState

I suspect this saves ~3.44ms for any MAUI app startup, and a small
amount more depending on the number of string comparisions happening.
@@ -91,7 +91,7 @@ protected override async Task HandleWebResourceRequest(CoreWebView2WebResourceRe
{
relativePath = _hostPageRelativePath;
}
relativePath = Path.Combine(_contentRootDir, relativePath.Replace("/", "\\"));
relativePath = Path.Combine(_contentRootDir, relativePath.Replace('/', '\\'));
Copy link
Member

Choose a reason for hiding this comment

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

Approved by
image

@jonathanpeppers jonathanpeppers merged commit c40c6e7 into dotnet:main Mar 1, 2022
@jonathanpeppers jonathanpeppers deleted the StringComparisonOrdinal branch March 1, 2022 23:33
@mattleibow mattleibow added this to the 6.0.300-rc.1 milestone Apr 5, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Dec 21, 2023
@Eilon Eilon added the t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf) label May 10, 2024
@samhouts samhouts added the fixed-in-6.0.200-preview.14.2 Look for this fix in 6.0.200-preview.14.2! label Aug 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
fixed-in-6.0.200-preview.14.2 Look for this fix in 6.0.200-preview.14.2! legacy-area-perf Startup / Runtime performance t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants