Skip to content

Conversation

@ThomasGoulet73
Copy link
Contributor

@ThomasGoulet73 ThomasGoulet73 commented May 4, 2023

Description

I improved performance and allocations by using spans and using ordinal ignore case comparison instead of allocating new strings with ToUpper.

Here's the result of my benchmark (I'll post the code soon):

BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.2846/22H2/2022Update)
Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET SDK=8.0.100-preview.3.23178.7
  [Host]     : .NET 8.0.0 (8.0.23.17408), X64 RyuJIT AVX2
  DefaultJob : .NET 8.0.0 (8.0.23.17408), X64 RyuJIT AVX2

Method id familyName fontCollection Mean Error StdDev Median Ratio RatioSD Code Size Gen0 Allocated Alloc Ratio
LookupFamilyOld 1 Font1 Syste(...)mily] [80] 15.032 ns 0.1291 ns 0.1145 ns 15.070 ns 1.00 0.00 1,843 B 0.0331 104 B 1.00
LookupFamilyNew 1 Font1 Syste(...)mily] [80] 4.219 ns 0.1353 ns 0.1130 ns 4.243 ns 0.28 0.01 3,364 B - - 0.00
LookupFamilyOld 2 Font1 Face1 Syste(...)mily] [80] 319.038 ns 14.1718 ns 41.7859 ns 291.383 ns 1.00 0.00 4,155 B 0.1783 560 B 1.00
LookupFamilyNew 2 Font1 Face1 Syste(...)mily] [80] 171.464 ns 1.3229 ns 1.1727 ns 171.683 ns 0.52 0.07 2,536 B 0.1044 328 B 0.59
LookupFamilyOld 3 Font1 Face5 Syste(...)mily] [80] 426.723 ns 5.4717 ns 7.8474 ns 428.868 ns 1.00 0.00 4,155 B 0.1373 432 B 1.00
LookupFamilyNew 3 Font1 Face5 Syste(...)mily] [80] 232.649 ns 3.8664 ns 3.4275 ns 233.997 ns 0.55 0.01 2,536 B 0.0229 72 B 0.17
LookupFamilyOld 4 Font1 Face50 Syste(...)mily] [80] 2,531.224 ns 27.8396 ns 42.5140 ns 2,550.462 ns 1.00 0.00 4,155 B 0.7057 2216 B 1.00
LookupFamilyNew 4 Font1 Face50 Syste(...)mily] [80] 1,499.158 ns 14.6092 ns 13.6655 ns 1,502.840 ns 0.59 0.01 2,536 B 0.0229 72 B 0.03

Customer Impact

Better perf.

Regression

No.

Testing

I ran FamilyCollection.LookupFamily with different combinations to make sure that the result was the same.

Risk

Low.

Microsoft Reviewers: Open in CodeFlow

@ThomasGoulet73 ThomasGoulet73 requested a review from a team as a code owner May 4, 2023 04:04
@ghost ghost assigned ThomasGoulet73 May 4, 2023
@ghost ghost added the PR metadata: Label to tag PRs, to facilitate with triage label May 4, 2023
@ghost ghost requested review from dipeshmsft and singhashish-wpf May 4, 2023 04:05
@ghost ghost added the Community Contribution A label for all community Contributions label May 4, 2023
{
string currentFontName = name.Value.ToUpper(CultureInfo.InvariantCulture);
if (currentFontName == faceName)
if (faceName.Equals(name.Value, StringComparison.OrdinalIgnoreCase))
Copy link
Contributor

Choose a reason for hiding this comment

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

I am concerned about switching from invariant to ordinal. Using NLS, this no longer matches for example "ss" with "ß".

Not only that, I don't quite understand why the CultureInfo associated with that face name (i.e. name.Key) shouldn't be used for this comparison?

Applies to the dictionary too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure it is that big of a concern, it was already using ordinal comparison but using InvariantCulture for the "ignore case" part. So the only thing that this PR could change is in the case where faceName.Equals(name.Value, StringComparison.OrdinalIgnoreCase) != faceName.ToUpper(CultureInfo.InvariantCulture).Equals(name.Value.ToUpper(CultureInfo.InvariantCulture), StringComparison.Ordinal). Are you aware of any cases where this would apply ?

Copy link
Contributor

@miloush miloush May 9, 2023

Choose a reason for hiding this comment

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

Good point! But yes, I am. For NLS, the Deseret characters (starting with U+10400). For ICU, the Vithkuqi characters (starting with U+10570).

You convinced me though that the change is not worse than the existing behavior. I disagree that face names should be compared using ordinal rules in principle, but that is a separate issue.

Copy link
Contributor

Choose a reason for hiding this comment

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

just be aware of this: http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html

(and I thought temporary fonts can have crazy (random) names).

…Cache/FamilyCollection.cs

Co-authored-by: halgab <24685886+halgab@users.noreply.github.com>
@miloush
Copy link
Contributor

miloush commented May 9, 2023

LGTM

@ThomasGoulet73 ThomasGoulet73 added the Performance Performance related issue label May 9, 2023
@lindexi
Copy link
Member

lindexi commented May 17, 2023

Awesome

@dipeshmsft
Copy link
Member

@ThomasGoulet73 this is a good perf improvement. Thanks for your constant efforts.

@ThomasGoulet73
Copy link
Contributor Author

Thank you @dipeshmsft

@ThomasGoulet73 ThomasGoulet73 deleted the perf-font-FamilyCollection.LookupFamily branch June 12, 2023 12:42
@ghost ghost locked as resolved and limited conversation to collaborators Jul 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Community Contribution A label for all community Contributions Performance Performance related issue PR metadata: Label to tag PRs, to facilitate with triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants