3

I noticed that the primitive types in C# are really just implemented as aliases to structs defined in the System namespace, e.g. ulong is an alias to the System.UInt64, which is of struct type. Is there any additional space-time overhead to the primitive types in C# arising from this? Say, does ulong really consume only 8 bytes of memory?

In spirit, this should test the memory overhead:

using System;

class Program
{
    static void Main()
    {
        long beforeAlloc = GC.GetTotalMemory(false);
        ulong[] myArray = new ulong[System.Int32.MaxValue];
        myArray[0] = 1;
        long afterAlloc = GC.GetTotalMemory(false);

        Console.WriteLine(((afterAlloc - beforeAlloc) / System.Int32.MaxValue).ToString());
     }
}

But the documentation specifies that GC.GetTotalMemory() method only retrieves the number of bytes currently thought to be allocated, so is there no easy way of finding out without a more sophisticated memory profiler?

elleciel
  • 2,297
  • 3
  • 17
  • 19

2 Answers2

3

There is no overhead from a struct itself. However, the runtime is free to pad any compound types as an alignment optimization.

For details about how arrays are handled at run-time please see this question.

Community
  • 1
  • 1
Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
  • Thanks! I have 2 follow-up questions, (1) Is there any quick but more reliable approach than `GC.GetTotalMemory()` to test this hypothesis? (2 - not related to the main question) Since the runtime pads the compound types, is there an advantage of re-arranging the struct members from large to small size a la C standard? – elleciel Sep 11 '14 at 21:25
  • 1
    It depends on what you're looking for. Remember, that the CLR acts as a menory manager on behalf of your application, so it will allocate and free memory at the OS level. The real question here is probably why do you want to know? – Brian Rasmussen Sep 11 '14 at 21:28
  • Just out of curiosity. I was playing with the locations of structs allocated on different parts of the address space in C and decided to look at other languages and came across this strange spec in C#. I guess it's a nice trick to know if I can squeeze a struct into 1 or 2 cache lines by rearranging the struct members. :) – elleciel Sep 11 '14 at 21:35
  • @BrianRasmussen Would a struct containing a single int have more overhead than just an int? ie `Struct MyInt { int a; }` vs `int a;` – lozzajp Oct 21 '16 at 14:15
1

The primitive types are aliased by the compiler. There is no difference in the resulting code whether you use int or System.Int32. In your example, System.UInt64 and ulong are both structs; they both inherit from System.ValueType. This is because, in fact, they are the same type.

The compiler will be marginally quicker, however, if you use the keywords. When you use, for example, Int32, the compiler resolves the type name from among all other types in scope, with attention to the namespace and using directives, to determine that the type isn't some other Int32 type that someone else wrote. This doesn't happen with the aliases.

If you can find an example where this difference is actually measurable, I'd be very surprised!

phoog
  • 42,068
  • 6
  • 79
  • 117