I am using .NET Memory Profiler from SciTech to reduce memory allocations rate of my program and cut frequency of garbage collections.
Surprisingly, according to the profiler, the largest amount of allocations seems to be coming from GCHandle.Alloc calls I am doing to marshall existing .NET arrays to native OpenGL.
My understanding is that calling GCHandle.Alloc does not allocate memory, it only pins existing memory on the managed heap?
Am I wrong or is the profiler wrong?
.NET reference source is available for anyone to see, and you can have a look and find out for yourself.
If you dig into
GCHandle.Alloc, you'll see the it calls a native method called
[System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ResourceExposure(ResourceScope.None)] internal static extern IntPtr InternalAlloc(Object value, GCHandleType type);
Drilling down into the CLR code, you see the internal call to
MarshalNative::InternalAlloc, which ends up calling:
hnd = GetAppDomain()->CreateTypedHandle(objRef, type);
Which in turns calls
HandleTableCache->TableAllocSingleHandleFromCache which allocates the handle if the it doesn't exist in the cache.
As @Antosha corrected me, the place of invocation isn't via
ComDelegate (which actually makes little since) but via
MarshalNative. An allocation does occur, not on the managed heap, but an external heap reserved by the runtime for managing handle roots into GC objects. The only allocation that does occur in the managed heap is the
IntPtr which holds to pointer to the address in the table. Despite this, you should still make sure to call
GCHandle.Free once you're done.