Skip to content

Optimize virtcall by using struct instead of class for innermap #105

Description

@devedse

I want to performance optimize: AlgorithmBacktrack2Deluxe2_AsByte

So I did some testing and if we would do this:

  public Maze GoGenerate<M, TAction>(int width, int height, int seed, IInnerMapFactory<M> mapFactory, IRandomFactory randomFactory, TAction pixelChangedCallback)
            where M : InnerMap
            where TAction : struct, IProgressAction
        {
            var innerMap = mapFactory.Create(width, height);
            var random = randomFactory.Create(seed);

            // Special handling for our unsafe map
            if (innerMap is BitArreintjeFastInnerMapUnsafe unsafeMap)
            {
                return GoGenerateInternalUnsafe(unsafeMap, random, pixelChangedCallback);
            }
            
            // Fallback (or throw, but let's try to be nice)
            // But since I don't want to duplicate the safe logic here, I'll just throw 
            // because the user selected the "Unsafe" algorithm implying they want speed.
            throw new InvalidOperationException($"AlgorithmBacktrack3_Unsafe requires BitArreintjeFastInnerMapUnsafe, but got {innerMap.GetType().Name}");
        }
        private unsafe Maze GoGenerateInternalUnsafe<TAction>(BitArreintjeFastInnerMapUnsafe map, IRandom random, TAction pixelChangedCallback)
            where TAction : struct, IProgressAction
        {

Then purely the fact that we use BitArreintjeFastInnerMapUnsafe instead of a generic, optimizes the maze generation algorithm performance quite significantly.

The reason for that is is because we now use the actual class BitArreintjeFastInnerMapUnsafe (which is sealed) rather then the implementation.

The problem is though that the only way to get C# to inline methods in the old method like this:

        private Maze GoGenerateInternal<M, TAction>(M map, IRandom random, TAction pixelChangedCallback) where M : InnerMap where TAction : struct, IProgressAction
        {

Is to ensure that M is actually also a struct, just like IProgressAction.

So what I want you to do is somehow create a wrapper or whatever around the InnerMap with struct functionality so we can get that inlined WITHOUT modifying the AlgorithmBacktrack2Deluxe2_AsByte to have specific code for the maze.

SO DO NOT ADD SOMETHING LIKE THIS:
if (innerMap is BitArreintjeFastInnerMapUnsafe unsafeMap).

Think of other solutions

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions