Search code examples
c#optimizationmemory

How are C# class methods stored in memory?


I am creating a voxel type game and I am wondering how an objects methods are stored.

public class Voxel
{
    byte x, y, z;
    public virtual void Build(){}
}

public class Flat : Voxel 
{
    public override void Build(){}
}

If I am instancing this 1 million times with different child classes of voxel then does having more methods slow it down? Should I limit the class as much as possible and use no methods or do the methods get stored once in memory?


Solution

  • If I am instancing this 1 million times with different child classes of voxel then does having more methods slow it down?

    No, it does not. Methods are not stored in an instance of a class. All methods (static or not) are part of the class, not the instance. The only difference with instance methods is that they have an implicit "context" / this pointer as first argument. This is all handled by C# itself. Though class instances in general have quite a bit of overhead. We can't really give exact figures as this depends on the architecture (32 / 64 bit) and some other factors like alignment. Also when your class has virtual / abstract methods it needs a v-table to define where it can find the concrete method implementations. Though the v-table for a class also exits only once per concrete type. The instance has a pointer to that table. Non-virtual methods are resolved through the variable type while virtual methods go through dynamic dispatch by using the v-table.

    So the number of methods do not matter. As I said, classes can be a bit tricky when it comes to the overall memory overhead. However structs are a lot simpler as they can not be derived and can not have virtual methods. Because of that a struct instance does not contain any type information but just the pure data, regardless of how many methods it may have.

    Instance methods work actually pretty similar to C#'s extension methods. Almost all code in C# is static code with very few exceptions. Most of those exceptions like generics just require an initial just-in-time compilation step and are also static from that point on.

    For most voxel engines it's quite unusual to store the x,y,z position inside the instance. You usually want to limit the data as much as possible. The position is usually an inferred property from the location in an array / grid and may be passed down to the necessary methods. Minecraft's block types are classes, but each of those classes only have a single instance which represents the blocktype. So each block uses the same instance to do the virtual method magic. Since structs are value types, you could wrap a block with a struct and have the struct "drag along" the position for convenience. Though this goes way to deep into specific design choices. On the bottom line, you usually don't want to represent each voxel with a class instance for various reasons.