dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.45k stars 4.76k forks source link

[API Proposal]: Add source-generator for enum type #92529

Open HakamFostok opened 1 year ago

HakamFostok commented 1 year ago

Background and motivation

Andrew Lock (Microsoft MVP) created NetEscapades.EnumGenerators library Basically, it is a source generator that emits static methods for a specific enum that is equivalent to the methods provided by the Enum static class. But the catch here is those source-generated methods do not use reflection so their performance is much faster. here is a benchmark from Andrew Lock's article

  1. Benchmark for standard ToString method vs source-generated ToString method image

  2. Benchmark for Enum.IsDefined method which uses reflection vs source-generated IsDefined method image

Those benchmarks could excite only @stephentoub

I know showing only the benchmark is not enough and the code is needed, but all the details are in the article mentioned above.

I hope, one day, those source-generators can find their ways to be first-class citizens in .NET. Thank you very much for all your efforts to make .NET the best .NET possible.

API Proposal

namespace System;

[AttributeUsage(AttributeTargets.Enum)]
public sealed class EnumGenerator : Attribute
{
}

API Usage

[EnumGenerator]
public enum SomeEnum 
{
   value1,
   value2
}

Alternative Designs

No response

Risks

No response

EgorBo commented 1 year ago

This idea was discussed here: https://github.com/dotnet/runtime/issues/57748#issuecomment-971564143

HakamFostok commented 1 year ago

Hi @EgorBo, I checked the issue you mentioned, actually, it is one part of this suggestion, it is talking only about ToString, the library I mentioned is about all the static methods that are defined in the Enum class. for example IsDefined, GetValues, GetNames ext. so the scope is a little bit broader here, but I see there, maybe there is a trend to keep .NET as base, and encouragement to do those things as Nuget packages (which, I understand, is fine and for the general good) I just wanted to suggest that, thank you very much

ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/area-system-runtime See info in area-owners.md if you want to be subscribed.

Issue Details
### Background and motivation Andrew Lock (Microsoft MVP) created [NetEscapades.EnumGenerators](https://github.com/andrewlock/NetEscapades.EnumGenerators) library Basically, it is a source generator that emits static methods for a specific enum that is equivalent to the methods provided by the [`Enum`](https://learn.microsoft.com/en-us/dotnet/api/system.enum) static class. But the catch here is those source-generated methods do not use reflection so their performance is much faster. here is a benchmark from [Andrew Lock's article](https://andrewlock.net/netescapades-enumgenerators-a-source-generator-for-enum-performance/) 1. Benchmark for standard `ToString` method vs source-generated `ToString` method ![image](https://github.com/dotnet/runtime/assets/12747172/60b0a359-6653-455f-a1a9-2fd1feb2c3b1) 2. Benchmark for `Enum.IsDefined` method which uses reflection vs source-generated `IsDefined` method ![image](https://github.com/dotnet/runtime/assets/12747172/453a87bb-153e-46a4-ab01-bbb11ea8ceaa) Those benchmarks could excite only @stephentoub I know showing only the benchmark is not enough and the code is needed, but all the details are in the article mentioned above. I hope, one day, those source-generators can find their ways to be first-class citizens in .NET. Thank you very much for all your efforts to make .NET the best .NET possible. ### API Proposal ```csharp namespace System; [AttributeUsage(AttributeTargets.Enum)] public sealed class EnumGenerator : Attribute { } ``` ### API Usage ```csharp [EnumGenerator] public enum SomeEnum { value1, value2 } ``` ### Alternative Designs _No response_ ### Risks _No response_
Author: HakamFostok
Assignees: -
Labels: `api-suggestion`, `area-System.Runtime`, `untriaged`, `needs-area-label`
Milestone: -
Tornhoof commented 1 year ago

One of the general problems with many srcgen ideas which are used to replace a runtime lookup in a dictionary with some kind of compiled concept, usually some switch table is, that they scale rather badly. Even with quite small value lists, let's say a few dozen enums, the dictionary lookup is equally fast or even faster (also depends on things like consecutive numbers etc.).

Generally spoken, it is not trivial to map an arbitrary list of values onto a consecutive list of integers, e.g. for Array Indices. That specific problem is called perfect minimal hash function. The algorithms for that are all rather cpu intensive and with that not well-suited for a srcgen.