A trip through the performance of Enum.Parse() in .NET
I came across a performance bottleneck when trying to develop an evaluation function for Rudim which led me to make an alternative to Enum.Parse
I had finished implementing Rudim's evaluation function and had moved on to implementing Negamax with Alpha-Beta pruning as my search algorithm. Upon completing the search algorithm, I noticed that it performed horribly - so horribly that it wasn't even evaluating moves even 2% at the speed at which it would have if it had no evaluation function.
Rudim was struggling to calculate 160,000 nodes - taking 7.5 seconds to do so, which was way too low if Rudim expected to play good chess. So I set out to try and improve this.
Finding the Culprit
I had never used a profiler before - so this was the first time and it was pretty interesting seeing it's capabilities. Using Visual Studio's built in profiler, I was able to find the culprit, a small code block that was taking 60% of CPU time. That was WAY too much for what it did.
This was the function.
private static int
Such a tiny little function was hogging up 60% of the runtime of Rudim. To give a brief of what this function was intended for, I wanted a way to flip the board - e.g. square a1
, if the board was just flipped would be sitting where square a8
actually was. So, what I did was I created another Enum called MirroredSquare and put this in there.
public ;
public ;
Then the above implementation makes sense. It was (somewhat) clean, didn't involve too much code or magic calculations to find the mirror.
Changing the code
But now I needed a better approach, and had to try and make the simplest implementation of the above parsing.
Which led me to using a Dictionary
. A map from what we want to parse - to what it should parse. This would definitely improve the performance of the code by miles. Most use cases of Enum.Parse()
can be translated into a Dictionary
, and if your application is seeing some performance bottlenecks, this will definitely help - you just need to find out how to model your solution.
Mine looked something like this.
private static int
Now instead of just manually mapping all 64 squares to it's mirror in 64 lines of code, I did it programatically.
public static
Implementing the Dictionary
version brought the runtime for the same 160,000 nodes down to 1.7
seconds - a 400%
improvement!
For a detailed comparison of a Dictionary based approach vs Enum.Parse() you can check out this blog post by Mariusz Wojcik.