Fixing the performance problem of enums in C#

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody i'm nikki in this video i'm going to introduce you to a few performance issues with enums in c-sharp and show you how we can easily fix them now i have actually talked about a part of this in an old video i'm going to put it in the description in case you want to see it i will cover it in this video as well so you don't have to watch that video but if you want a more in-depth analysis of what's going on you can check that too if you like a lot of content and you want to see more make sure you subscribe bring the simplification bell and for more training check out nickjabson.com now real quick before i move on i want to let you know that we'll be running an in-person workshop called introduction to effective testing in csharpn.net in three conferences that's ndc oslo ndc minnesota and ndc sydney so check the links in the description and i hope to see you in person and if you're watching this in the future then check the description i might have updated with future workshops i'm gonna do in other places all right so what do we have here well i'm gonna show you what i have and where we're starting with i have this simple color enum here it has a bunch of colors i copied this from the known colors enum in dot net and i'm going to use that as an example because everyone understands colors it's an easy enum well unless you're color blind whatever so the point is that there are a few methods when you deal with enums for example let's say color dot light green and then if i go ahead and say console.writeline and print that in them what i'm going to say is light green the text now it is very common in dotted applications to also use the string representation of the enum not just integer i know some of you will say i never had to do this if you never had to do this that is fine but it is very common to be used in contracts error messages logs it is not an uncommon thing i've seen this a ton and i've used it personally a ton now if you watch that previous video you might have seen that the tostring method in enums is actually not really efficient if i go in there you're gonna see that it's doing a binary search it's building a cache it's it's doing a few things that are questionable at best however it is how it is and that's the only reality we know at this point now this is one of the methods we're looking to improve the second one is the enum dot try pause and this is a method you use by usually passing down the text version so say for example light green and then you say out color the color and this returns true or false if it matches it or not and if it did match it it will have populated this value from the text that you gave here this is the other one this is again very common if you're doing any dynamic stuff and this is just one of the overloads in that method and then another one which is very common is the enum dot is defined method in which you either have the generic overload or the type of i'm gonna go with typo and say type of color and i can specify the value now in this case i think light green happens to be oh yeah so it happens to be this one so i'm just gonna say this and if that is part of the enum it's going to return whether it is defined in that enum or not so if i go to another random one which is way out of scope it will not return anything this will return true so these are the most common methods you will be dealing with in the enum world now what i'm going to do is i'm going to benchmark all of them in their current state with these implementations because i want to know where i am performance wise as i'm trying to optimize them so i'm going to bring in benchmark.net and i'm going to go real quick and add some benchmarks for them all right so here's my benchmark class first i have light green and i'm do stringing it to see how long this operation takes and how much memory it allocates then i have the is defined call which will tell me if this integer exists as a color in the color type which is an enum and then i'm doing the try pause to see if it could pause it or not and return the value so to run this i'm gonna go over here i'm just gonna quickly just comment all of this out i don't need it and i'm gonna say benchmark runner dot run and i'm gonna say benchmarks over here i turn this into release mode and then simply run the benchmarks and see how our current operations in the built-in bcl perform all right so results are back and if i expand this you can see that we have uh 20 nanoseconds for the two-string one 75 nanoseconds for the is defined and 111 nanoseconds for the try pause and we actually have some memory allocation in the first two which isn't great but you know 24 bytes is not much right well let's see how we can actually fix this because a lot of that information that we're searching for here is actually based on static data data that doesn't change so it could be based purely on compile-time data however this is not the case now how can we fix this well in my previous video i had the call to action out and i said that if someone wants to make a source generator that generates all that code automatically then you can do it and you will see great gains and one of the people who did that probably not because he watched my video but because it is a no-brainer because this has been raised by people like david fowler as well is andrew locke now andrew locke in case you don't know him he has a great blog i'm gonna put it in the description he has blogged about this package as well go check it out if you want he has one new blog every week highly recommended and because we're talking about an open source package in this video like with all my videos i highly recommend you click the link in the description and you're going to give a star to the project open source developers can use all the styles they can get on github so please if you like what you see consider giving it a start right so i'm gonna go ahead and i'm gonna search for enum generators and it's the net escapades dot enum generators package it is in pre-release so keep that in mind i'm gonna go ahead and add it in the project and now what i'm going to do is show you how easy it is to make a source generator for your enum so all i'm going to do is go to the top of my enum and i'm going to say enum extensions and that's it and now what's happening behind the scenes is a source generator is kicking in it's inspecting this enum and it's generating extension methods and as you can see now we have 1423 usages these are all usages in the code that this source generator created now i'm gonna show you directly the results before i show you what's generated behind the scenes so what i'm going to do is create duplicates for those benchmarks and show you what the optimized or source generated version of all of these looks like and how it performs so i'm going to say enum2string fast and the way this works in this case is i get a new extension called tostring fast then i'm going to create a duplicate for this is defined and i'm going to say is defined fast just to distinguish between the two versions and what this did is i can now have a color extension so it's using the enum name and then it slaps the extensions suffix to differentiate and i have these the same is defined thing now in this case because it knows that the type is a color directly i don't need the first argument so all i need to do is this and then for the last one try pause i'm gonna say again fast and now same thing caller extension so the name of the enum and the extensions and i didn't even have to change the signature it is the exact same signature as it was before and now i have everything and what i'm going to do is simply run the benchmarks and once this is done we're going to see how it compares both in speed and memory all right so results are back and let's see what we have here so let's compare one after the other so the two string the built in in m2 string is like we said before 20 nanoseconds the optimized version with the source generator one nanosecond so 20 times faster here and no memory allocation this is big then we have the is defined 75 times faster again no more relocation and then the enum try pause which is many times faster and we didn't have any memory allocated before so that is fine so as you can see this is no small potatoes i mean it is nanoseconds but this memory you're saving here depending on how much you're using it you could see a difference so if you're using enums in that way i highly recommend you take a look to this package you use it it is still technically pre-released but the more you use it the more andrew will be comfortable moving it to a full release now let's see what the package is actually doing behind the scenes because i think that's very interesting oh and by the way in case you're wondering if you want to have a different display name for an enum value you could easily say display and then say name equals and then in this case use something else for for this specific one so you could do it like this and the source generator will respect it in any case let's see how this is working behind the scenes so if i go to the too fast string method which is a source generated method as you can see it's switching on the enum now you might say well nick if it's a very big enum then this will actually be slow no it's not unless you have like 10 20 000 items in the in the enum it won't be slower so don't worry about it it's fine it's faster so that is how the the tostring is working then the is defined similar fashion does it match the thing true or false it is all statically accessible data and in the end the default just says false makes sense um then we saw that is defined and the other one is well is defined has a few other loads and then the other one is a try pause you also have a tripod ignore case um let's go ahead and see what's in this try pause method here we go so again you have switches you have cases and if it is part of the default uh case which damn that's a long enum um then it will return the false value and the default value now one of the things i noticed when i was playing around with this package was that there's a couple of methods that i don't like how they work behind the scenes and i hope andrew or someone else who wants to contribute to the project sees this and fixes it is that the getvalues method which gives you all the values in the inum in an array and the get names method they both return a new array every single time so even though there are static methods they don't assign that to a backing field so they never cache it so you allocate a new string array every single time don't do that have a field cast the value return from that cast value every single time so if you're watching this and you want to contribute to the package this is a great first and pull request in any case like i said before this is a great nuget package i highly recommend you give it a star on github for people like me who want to write super efficient code this is a no-brainer and i'm happy that people are using source generators to optimize code like this to be even faster and more more efficient well that's all i had for you first video thank you very much for watching special next to my patreons for making videos possible if you want to support me as well you're going to find it in the description down below leave a like if you like this video subscribe smoke them like this hearing the bell as well and i'll see you in the next video keep coding you
Info
Channel: Nick Chapsas
Views: 49,865
Rating: undefined out of 5
Keywords: Elfocrash, elfo, coding, .netcore, dot net, core, C#, how to code, tutorial, development, software engineering, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, dotnet, .net, enum generator, enum c#, enum source generator, enum performance, enum nick chapsas, nick chapsas enums, Fixing all my complaints with enums in C#, fixing enums in c#, fixing enums, enums c#, enum performance c#
Id: -RX6XKHkjOs
Channel Id: undefined
Length: 11min 18sec (678 seconds)
Published: Thu Jun 09 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.