views:

304

answers:

3

I found a blog entry which suggests that sometimes c# compiler may decide to put array on the stack instead of the heap:

Improving Performance Through Stack Allocation (.NET Memory Management: Part 2)

This guy claims that:

The compiler will also sometimes decide to put things on the stack on its own. I did an experiment with TestStruct2 in which I allocated it both an unsafe and normal context. In the unsafe context the array was put on the heap, but in the normal context when I looked into memory the array had actually been allocated on the stack.

Can someone confirm that?
I was trying to repeat his example, but everytime I tried array was allocated on the heap.

If c# compiler can do such trick without using 'unsafe' keyword I'm specially intrested in it. I have a code that is working on many small byte arrays (8-10 bytes long) and so using heap for each new byte[...] is a waste of time and memory (especially that each object on heap has 8 bytes overhead needed for garbage collector).

EDIT: I just want to describe why it's important to me:
I'm writing library that is communicating with Gemalto.NET smart card which can have .net code working in it. When I call a method that returns something, smart card return 8 bytes that describes me the exact Type of return value. This 8 bytes are calculated by using md5 hash and some byte arrays concatenations.
Problem is that when I have an array that is not known to me I must scan all types in all assemblies loaded in application and for each I must calculate those 8 bytes until I find the same array.
I don't know other way to find the type, so I'm trying to speed it up as much as possible.

A: 

System.Array (the class representing an array) is a reference type and lives on the heap. You can only have an array on the stack if you use unsafe code.

I can't see where it says otherwise in the article that you refer to. If you want to have a stack allocated array, you can do something like this:

decimal* stackAllocatedDecimals = stackalloc decimal[4];

Personally I wouldn't bother- how much performance do you think you will gain by this approach?

This CodeProject article might be useful to you though.

RichardOD
In a tight loop the performance improvement can be very large. Also, avoiding repeated heap allocations will prevent heap fragmentation. This is much the same as why it is good to use a StringBuilder instead of repeatedly creating new immutable instances of the String class which then need to be cleaned up by the garbage collector.
Rick Minerich
@Rick- sure it might improve performance a lot- unless you profile the app though you don't know if this is the root cause of a performance issue.
RichardOD
+1  A: 

From your line:

I have a code that is working on many small byte arrays (8-10 bytes long)

Personally, I'd be more interested in allocating a spare buffer somewhere that different parts of your code can re-use (while processing the same block). Then you don't have any creation/GC to worry about. In most cases (where the buffer is used for very discreet operations) with a scratch-buffer, you can even always assume that it is "all yours" - i.e. every method that needs it can assume that they can start writing at zero.

I use this single-buffer approach in some binary serialization code (while encoding data); it is a big boost to performance. In my case, I pass a "context" object between the layers of serialization (that encapsulates the scratch-buffer, the output-stream (with some additional local buffering), and a few other oddities).

Marc Gravell
Because thise Type scanning can be easy pipelined I wrote extension method that allocated this array only once and used yield return. Thanks for suggestion :-)
SeeR
A: 

Hello, Author of the linked-to article here.

It seems impossible to force stack allocation outside of an unsafe context. This is likely the case to prevent some classes of stack overflow condition.

Instead, I recommend using a memory recycler class which would allocate byte arrays as needed but also allow you to "turn them in" afterward for reuse. It's as simple as keeping a stack of unused byte arrays and, when the list is empty, allocating new ones.

Stack<Byte[]> _byteStack = new Stack<Byte[]>();

Byte[] AllocateArray()
{
Byte[] outArray;
if (_byteStack.Count > 0)
  outArray = _byteStack.Pop(); 
else
  outArray = new Byte[8];
return outArray;
}

void RecycleArray(Byte[] inArray)
{
  _byteStack.Push(inArray);
}

If you are trying to match a hash with a type it seems the best idea would be to use a Dictionary for fast lookups. In this case you could load all relevant types at startup, if this causes program startup to become too slow you might want to consider caching them the first time each type is used.

Rick Minerich