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
Reduce allocations #26
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -220,86 +220,94 @@ internal string Pluralize(string locale, ParsedArguments arguments, PluralContex | |||
/// <returns> | |||
/// The <see cref="string" />. | |||
/// </returns> | |||
internal string ReplaceNumberLiterals(StringBuilder pluralized, double n) | |||
internal string ReplaceNumberLiterals(string pluralized, double n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder, is there a way to use Span
for perf here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, we get the pluralized
value from the cached strings, so I think we can't
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can try using Span APIs more via changing for index StringBuilder loops to GetChunks in NET5.0, but that's a sizeable piece of work in itself )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so you think GetChunks
is faster than an index accessor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, index accessor basically does a lot of duplicating work when iterating through the whole StringBuilder (finds the chunk where the idx is each time)
See here https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs#L497
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah nice find! If we can run the tests against .NET 5 as well as the one that does not support it, I would not be opposed to having 2 different implementations of the most critical paths. Alternatively, we can just bump support to the lowest target that supports Span
(even in its less optimal form which should still be more performant)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GetChunks API is available starting from netcoreapp3.0
https://docs.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.getchunks?view=net-5.0
I prefer multitargeting for now, because netstandard2.1 does not have the APIs required, and the only next version after netstandard2.0 (that supports both Mono and CoreCLR) with the APIs is net5.0
#if NET5_0_OR_GREATER | ||
foreach (var chunk in src.GetChunks()) | ||
{ | ||
if (chunk.Span.IndexOfAny(chars) != -1) | ||
{ | ||
return true; | ||
} | ||
} | ||
#else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥🔥🔥🔥🔥🔥🔥🔥
@@ -18,6 +18,7 @@ | |||
</PropertyGroup> | |||
|
|||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="5.0.5" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this is as performant as the Roslyn internal pool 🤔
Fixed the warning, analyzers are happy now |
Excellent work @kostya9 !! 🚀 |
Noticed some low-hanging fruit when working on parsing CLDR.
Before
After
Benchmark code