5
  1. How big is instance of following class after constructor is called? I guess this can be written generally as size = nx + c, where x = 4 in x86, and x = 8 in x64. n = ? c = ?
  2. Is there some method in .NET which can return this number?

class Node { byte[][] a; int[] b; List<Node> c; public Node() { a = new byte[3][]; b = new int[3]; c = new List<Node>(0); } }

watbywbarif
  • 6,487
  • 8
  • 50
  • 64

1 Answers1

5

First of all this depends on environment where this program is compiled and run, but if you fix some variables you can get pretty good guess.

Answer to 2) is NO, there is no function that will give you requested answer for any object given as argument.

In solving 1) you have two approaches:

  • Try to perform some tests to find out
  • Analyze the object and do the math

Test approach

First take a look at these:

Method you need is this:

const int Size = 100000;
private static void InstanceOverheadTest()
{
    object[] array = new object[Size];
    long initialMemory = GC.GetTotalMemory(true);
    for (int i = 0; i < Size; i++)
    {
        array[i] = new Node();
    }
    long finalMemory = GC.GetTotalMemory(true);
    GC.KeepAlive(array);
    long total = finalMemory - initialMemory;
    Console.WriteLine("Measured size of each element: {0:0.000} bytes",
                      ((double)total) / Size);
}

On my Windows 7 machine, VS 2012, .NET 4.5, x86 (32 bit) result is 96.000. When changed to x64 result is 176.000.

Do the math approach

Do the math approach can be written as a function that will give you result, but is specific for your Node class, and it is only valid before other operations on your object are performed. Also notice that this is made in 32-bit program and also note that this number can change with framework implementation and version. This is just example how you can give pretty good guess about object size in some moment if object is simple enough. Array and List overhead constants are taken from Overhead of a .NET array? and C# List size vs double[] size

public const int PointerSize32 = 4;
public const int ValueArrayOverhead32 = 12;
public const int RefArrayOverhead32 = 16;
public const int ListOverhead32 = 32;
private static int instanceOverheadAssume32()
{
    int sa = RefArrayOverhead32 + 3 * PointerSize32;
    int sb = ValueArrayOverhead32 + 3 * sizeof(int);
    int sc = ListOverhead32;
    return 3 * PointerSize32 + sa + sb + sc;
}

This will also return 96 so I assume that method is correct.

Community
  • 1
  • 1
watbywbarif
  • 6,487
  • 8
  • 50
  • 64
  • To show the danger of math approach I will not edit the answer. I just realized that in some more complex case I have difference between two approaches, so I did more digging. First i didn't take object overhead in calculation, but i linked this with thread about it so that you can read. Object adds 12B in my case, but this is reduced to 8B when object has some useful member. But this was compensated with bad ListOverhead32 which is only 24B when List is empty because internally used array is not yet initialized. Very easy to make error with this approach, measuring it feels more secure! – watbywbarif Apr 11 '14 at 06:50