Improve performance of Enum.{Try}Parse by stephentoub · Pull Request #21214 · dotnet/coreclr (original) (raw)
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Conversation42 Commits2 Checks0 Files changed
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
[ Show hidden characters]({{ revealButtonHref }})
- Non-generic TryParse with a string (e.g. "Wednesday" for DayOfWeek) is ~10% faster.
- Non-generic TryParse with a value (e.g. "3") is ~2x faster and with 50% less allocation.
- Generic {Try}Parse with a string is ~2.2x faster and with 0 allocation.
- Generic {Try}Parse with a value is ~5.5x faster and with 0 allocation.
- Avoids an exception being thrown/caught in both generic/non-generic TryParse with input like "3W", which makes that corner case hundreds of times faster.
Method | Before Allocation (b) | After Allocation (b) | Allocation Reduction | Before Time (ns) | After Time (ns) | Time Improvement |
---|---|---|---|---|---|---|
NameGenericByte | 24 | 0 | 100% | 181.8 | 82.6 | 2.20x |
NameGenericSByte | 24 | 0 | 100% | 178.8 | 82.98 | 2.15x |
NameGenericInt16 | 24 | 0 | 100% | 183 | 83.75 | 2.19x |
NameGenericUInt16 | 24 | 0 | 100% | 177 | 80.42 | 2.20x |
NameGenericInt32 | 24 | 0 | 100% | 184.7 | 82.18 | 2.25x |
NameGenericUInt32 | 24 | 0 | 100% | 181.6 | 80.96 | 2.24x |
NameGenericInt64 | 24 | 0 | 100% | 175.9 | 80.68 | 2.18x |
NameGenericUInt64 | 24 | 0 | 100% | 173.3 | 83.19 | 2.08x |
ValueGenericByte | 48 | 0 | 100% | 259.2 | 53.38 | 4.86x |
ValueGenericSByte | 48 | 0 | 100% | 285.2 | 50.8 | 5.61x |
ValueGenericInt16 | 48 | 0 | 100% | 285 | 50.69 | 5.62x |
ValueGenericUInt16 | 48 | 0 | 100% | 282.9 | 51.7 | 5.47x |
ValueGenericInt32 | 48 | 0 | 100% | 287.6 | 51.5 | 5.58x |
ValueGenericUInt32 | 48 | 0 | 100% | 287.6 | 50.73 | 5.67x |
ValueGenericInt64 | 48 | 0 | 100% | 267.8 | 51.39 | 5.21x |
ValueGenericUInt64 | 48 | 0 | 100% | 260.1 | 51.21 | 5.08x |
NameNonGenericByte | 24 | 24 | 0% | 185.8 | 166.09 | 1.12x |
NameNonGenericSByte | 24 | 24 | 0% | 179.5 | 164.55 | 1.09x |
NameNonGenericInt16 | 24 | 24 | 0% | 180 | 166.05 | 1.08x |
NameNonGenericUInt16 | 24 | 24 | 0% | 182.2 | 165.6 | 1.10x |
NameNonGenericInt32 | 24 | 24 | 0% | 196.7 | 166.21 | 1.18x |
NameNonGenericUInt32 | 24 | 24 | 0% | 188.5 | 163.2 | 1.16x |
NameNonGenericInt64 | 24 | 24 | 0% | 188.2 | 168.33 | 1.12x |
NameNonGenericUInt64 | 24 | 24 | 0% | 186.3 | 164.1 | 1.14x |
ValueNonGenericByte | 48 | 24 | 50% | 269 | 135.52 | 1.98x |
ValueNonGenericSByte | 48 | 24 | 50% | 269.9 | 138.3 | 1.95x |
ValueNonGenericInt16 | 48 | 24 | 50% | 269.4 | 140.55 | 1.92x |
ValueNonGenericUInt16 | 48 | 24 | 50% | 269.2 | 132.48 | 2.03x |
ValueNonGenericInt32 | 48 | 24 | 50% | 270.7 | 135.12 | 2.00x |
ValueNonGenericUInt32 | 48 | 24 | 50% | 268.6 | 132.63 | 2.03x |
ValueNonGenericInt64 | 48 | 24 | 50% | 274 | 134.89 | 2.03x |
ValueNonGenericUInt64 | 48 | 24 | 50% | 266.1 | 134.63 | 1.98x |
FailNonGeneric | 576 | 0 | 100% | 32,366.10 | 99.99 | 323.69x |
Fixes https://github.com/dotnet/corefx/issues/594
Fixes https://github.com/dotnet/corefx/issues/11073
Contributes to https://github.com/dotnet/corefx/issues/15453
cc: @ahsonkhan, @jkotas, @GrabYourPitchforks, @joperezr
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some nits/questions. Otherwise, LGTM.
@dotnet-bot test CentOS7.1 x64 Debug Innerloop Build please
@dotnet-bot test Linux-musl x64 Debug Build please
@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test please
@dotnet-bot test Tizen armel Cross Checked Innerloop Build and Test please
Could you please fix the conflict?
In particular for the generic overloads, where this avoids all per-operation allocations when commonly used underlying types are used (for example, this improves when the underlying enum type is int but not double).
Could you please fix the conflict?
Rebased / fixed conflicts.
@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test please
@dotnet-bot test Windows_NT x64 Checked Innerloop Build and Test (Jit - TieredCompilation=0) please
stephentoub added a commit to dotnet/corefx that referenced this pull request
- Improve performance of Enum.{Try}Parse
In particular for the generic overloads, where this avoids all per-operation allocations when commonly used underlying types are used (for example, this improves when the underlying enum type is int but not double).
- Address PR feedback
Signed-off-by: dotnet-bot dotnet-bot@microsoft.com
Anipik pushed a commit to dotnet/corert that referenced this pull request
- Improve performance of Enum.{Try}Parse
In particular for the generic overloads, where this avoids all per-operation allocations when commonly used underlying types are used (for example, this improves when the underlying enum type is int but not double).
- Address PR feedback
Signed-off-by: dotnet-bot dotnet-bot@microsoft.com
jlennox pushed a commit to jlennox/corefx that referenced this pull request
- Improve performance of Enum.{Try}Parse
In particular for the generic overloads, where this avoids all per-operation allocations when commonly used underlying types are used (for example, this improves when the underlying enum type is int but not double).
- Address PR feedback
Signed-off-by: dotnet-bot dotnet-bot@microsoft.com
Benchmark.NET, then copying/pasting the results into Excel to compare. (With the --coreRun argument that was recently added to Benchmark.NET, this can be achieved more easily with the right set up locally.)
@stephentoub alright, I got things setup locally to benchmark my changes with the --coreRun argument. Do you happen to have the tests you used for this? I'd like to benchmark them with my changes.
Thanks, I saw that. I'll try to expand on those.
picenka21 pushed a commit to picenka21/runtime that referenced this pull request
- Improve performance of Enum.{Try}Parse
In particular for the generic overloads, where this avoids all per-operation allocations when commonly used underlying types are used (for example, this improves when the underlying enum type is int but not double).
- Address PR feedback
Commit migrated from dotnet/coreclr@88fb86f