Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# structs/classes stack/heap control?

so in c++ it's very easy. you want whatever class/struct to be allocated on the heap, use new. if you want it on the stack, don't use new.

in C# we always use the new keyword, and depending on whether it's a struct or a class it's allocated either on the stack or on the heap (structs go to the stack, classes to the heap) - and in some applications there can be a HUGE performance difference when changing the design such that only those objects go to the heap that really belong there.

What I wonder is - is there a direct way to control where an object is allocated independant of whether it's declared as struct or class? i know that value types (structs) can be boxed to go to the heap (but boxing/unboxing comes at a performance cost). is there a way to allocate classes on the stack?

Also, is there any mechanism to allocate raw memory and use something like placement new in C++? I know that this breaks with the idea of being managed - but it can make a big performance difference if you can use your custom memory management.

I love C# for it's convenience, for it's garbage collector and other things - but sometimes, when working on the bottleneck of an application, it meight be desirable to have more control over what is actually happening.

Any tips/hints welcome :)

edit: performance example:

struct Foo1
{
    public int i;
    public float f;
    public double d;
}

struct Foo2
{
   public Foo1[] bar;

   public void Init(){
        bar = new Foo1[100];
        for (int i = 0; i < 100; i++)
            bar[i] = new Foo1();
    }
}

class Program
{
    static void Main(string[] args)
    {
        DateTime time = DateTime.Now;
        Foo2[] arr = new Foo2[1000000];
        for (int i = 0; i < 1000000; i++)
        {
            arr[i] = new Foo2();
            arr[i].Init();
        }

        Console.WriteLine((DateTime.Now - time).TotalMilliseconds);
    }
}

This takes 1.8 seconds on my machine to execute (note that there is actually only allocation going on - no parameter passing)

if Foo1 is changed from struct to class, execution takes 8.9 seconds! that's five times slower

like image 467
Mat Avatar asked Jan 08 '10 22:01

Mat


1 Answers

While in the general case it's true that objects are always allocated on the heap, C# does let you drop down to the pointer level for heavy interop or for very high performance critical code.

In unsafe blocks, you can use stackalloc to allocate objects on the stack and use them as pointers.

To quote their example:

// cs_keyword_stackalloc.cs
// compile with: /unsafe
using System; 

class Test
{
   public static unsafe void Main() 
   {
      int* fib = stackalloc int[100];
      int* p = fib;
      *p++ = *p++ = 1;
      for (int i=2; i<100; ++i, ++p)
         *p = p[-1] + p[-2];
      for (int i=0; i<10; ++i)
         Console.WriteLine (fib[i]);
   }
}

Note however that you don't need to declare an entire method unsafe, you can just use an unsafe {...} block for it.

like image 179
Blindy Avatar answered Sep 30 '22 18:09

Blindy