Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Conversation

stephentoub
Copy link
Member

The allocation profile of Enum.Parse today is fairly poor. While the design of the method returning an Enum requires at least one allocation for the boxed result (the generic TryParse could be overhauled to avoid this, but still has it), additional allocations shouldn't be necessary in the common cases. However, for some reason the current code is boxing a 0 on every call. It's also using string.Trim() to remove whitespace (once for the overall string and then once for each substring), and using String.Split to parse multiple values, which ends up allocating a string[] and an int[] even if there's only one value.

This commit removes all allocations from Enum.Parse other than the boxing of the Enum result and some allocations on the code path where Enum.Parse is handed a string containing a number, in which case additional allocations are involved in using the Convert.ChangeType call.

With an enum like:

[Flags]
enum Colors
{
    Red = 0x1,
    Orange = 0x2,
    Yellow = 0x4,
    Green = 0x8,
    Blue = 0x10
}

using Enum.Parse(typeof(Color), "Red") repeatedly now results in 5x fewer gen0 GCs and is ~15% faster. Using Enum.Parse(typeof(Color), "Red, Orange, Yellow, Green, Blue") repeatedly now results in 23x fewer gen0 GCs is is similarly ~15% faster.

cc: @jkotas, @ellismg

StringComparison.OrdinalIgnoreCase :
StringComparison.Ordinal;

for (int valueIndex = 0; valueIndex <= value.Length; valueIndex++)
Copy link
Member

Choose a reason for hiding this comment

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

I think while (valueIndex <= value.Length) here would make it easier to understand.

Also, why is not the condition of the loop just valueIndex < value.Length? I guess it is handling some empty string corner case - comment on it would be nice.

Copy link
Member Author

Choose a reason for hiding this comment

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

The equals is to handle the case where the string ends with a comma.

I can change it to a while instead of a for.

@jkotas
Copy link
Member

jkotas commented Jan 30, 2016

LGTM. Very nice improvement.

The allocation profile of Enum.Parse today is fairly poor.  While the design of the method returning an Enum requires at least one allocation for the boxed result (the generic TryParse could be overhauled to avoid this, but still has it), additional allocations shouldn't be necessary in the common cases.  However, for some reason the current code is boxing a 0 on every call.  It's also using string.Trim() to remove whitespace (once for the overall string and then once for each substring), and using String.Split to parse multiple values, which ends up allocating a string[] and an int[] even if there's only one value.

This commit removes all allocations from Enum.Parse other than the boxing of the Enum result and some allocations on the code path where Enum.Parse is handed a string containing a number, in which case additional allocations are involved in using the Convert.ChangeType call.

With an enum like:
```C#
[Flags]
enum Colors
{
    Red = 0x1,
    Orange = 0x2,
    Yellow = 0x4,
    Green = 0x8,
    Blue = 0x10
}
```
using ```Enum.Parse(typeof(Color), "Red")``` repeatedly now results in 5x fewer gen0 GCs and is ~15% faster.  Using ```Enum.Parse(typeof(Color), "Red, Orange, Yellow, Green, Blue")``` repeatedly now results in 23x fewer gen0 GCs is is similarly ~15% faster.
@stephentoub
Copy link
Member Author

Thanks, @jkotas. Feedback addressed.

@jkotas
Copy link
Member

jkotas commented Feb 1, 2016

👍

jkotas added a commit that referenced this pull request Feb 1, 2016
Improve performance of Enum.Parse/TryParse
@jkotas jkotas merged commit f09b610 into dotnet:master Feb 1, 2016
stephentoub added a commit to stephentoub/corert that referenced this pull request Feb 6, 2016
Improve performance of Enum.Parse/TryParse
stephentoub added a commit to stephentoub/corert that referenced this pull request Feb 6, 2016
Improve performance of Enum.Parse/TryParse
jkotas added a commit to dotnet/corert that referenced this pull request Feb 7, 2016
@stephentoub stephentoub deleted the enum_parse branch February 12, 2016 12:47
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants