feat: optimise normalize helper#341
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #341 +/- ##
==========================================
+ Coverage 76.97% 77.01% +0.04%
==========================================
Files 40 40
Lines 4712 4730 +18
Branches 1115 1120 +5
==========================================
+ Hits 3627 3643 +16
Misses 851 851
- Partials 234 236 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR optimizes the internal normalization helper for modern .NET targets by introducing a Span-based NormalizeHelper(string, ...) implementation and conditionally compiling out the older StringBuilder-based string overload for those targets.
Changes:
- Added a NET5+/netstandard2.1
NormalizeHelper(string, ...)overload that writes into a stack-allocatedSpan<char>and constructs the resulting string from the slice. - Wrapped the existing StringBuilder-based
NormalizeHelper(string, ...)(inPhoneNumberUtil.cs) in a preprocessor guard so it only compiles for older targets.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| csharp/PhoneNumbers/PhoneNumberUtil.net.cs | Adds Span/stackalloc-based NormalizeHelper(string, ...) for NET5+/netstandard2.1 builds. |
| csharp/PhoneNumbers/PhoneNumberUtil.cs | Conditionally excludes the legacy NormalizeHelper(string, ...) for NET5+/netstandard2.1 so the new implementation is used. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// should be stripped from the number. If this is false, they | ||
| /// will be left unchanged in the number.</param> | ||
| /// <returns>The normalized string version of the phone number.</returns> | ||
| #if !(NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER) | ||
| private static string NormalizeHelper(string number, Func<char, char> normalizationReplacements, bool removeNonMatches) |
| if (number.Length == 0) return string.Empty; | ||
| Span<char> result = stackalloc char[number.Length]; | ||
| var resultLength = 0; | ||
| NormalizeHelper(ref result, ref resultLength, number, normalizationReplacements, removeNonMatches); |
📊 Benchmark Results
PR branch
|
| Method | Job | Runtime | PhoneNumberCount | Mean | Error | StdDev | Median | Gen0 | Gen1 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|
| ParseValidateAndFormatPhoneNumbers | .NET 8.0 | .NET 8.0 | 1000 | 2.275 ms | 0.0442 ms | 0.0574 ms | 2.265 ms | 35.1563 | - | 582.48 KB |
| ParseValidateAndFormatPhoneNumbers | .NET 9.0 | .NET 9.0 | 1000 | 2.083 ms | 0.0394 ms | 0.0602 ms | 2.052 ms | 35.1563 | - | 582.48 KB |
| ParseValidateAndFormatPhoneNumbers | .NET Framework 4.8 | .NET Framework 4.8 | 1000 | 5.953 ms | 0.1153 ms | 0.2275 ms | 5.884 ms | 226.5625 | 23.4375 | 1397.64 KB |
| ParseValidateAndFormatPhoneNumbers | .NET 8.0 | .NET 8.0 | 10000 | 22.895 ms | 0.3216 ms | 0.2851 ms | 22.827 ms | 343.7500 | - | 5818.97 KB |
| ParseValidateAndFormatPhoneNumbers | .NET 9.0 | .NET 9.0 | 10000 | 20.608 ms | 0.1151 ms | 0.0899 ms | 20.608 ms | 343.7500 | - | 5818.97 KB |
| ParseValidateAndFormatPhoneNumbers | .NET Framework 4.8 | .NET Framework 4.8 | 10000 | 62.352 ms | 1.2433 ms | 1.4318 ms | 61.944 ms | 2250.0000 | 250.0000 | 13961.16 KB |
| ParseValidateAndFormatPhoneNumbers | .NET 8.0 | .NET 8.0 | 100000 | 226.525 ms | 3.5386 ms | 3.1369 ms | 225.979 ms | 3333.3333 | - | 58180.04 KB |
| ParseValidateAndFormatPhoneNumbers | .NET 9.0 | .NET 9.0 | 100000 | 210.023 ms | 0.9001 ms | 0.7979 ms | 209.971 ms | 3333.3333 | - | 58180.04 KB |
| ParseValidateAndFormatPhoneNumbers | .NET Framework 4.8 | .NET Framework 4.8 | 100000 | 640.129 ms | 12.7096 ms | 26.5296 ms | 636.833 ms | 22000.0000 | 2000.0000 | 139529.64 KB |
Changes