Re: Garbage collectable pinned arrays!



"Ben Voigt [C++ MVP]" <rbv@xxxxxxxxxxxxx> wrote in message news:ummJ1AZbIHA.5164@xxxxxxxxxxxxxxxxxxxxxxx
The array is automatically allocated on the heap once it exceeds
a certain size and thu's becomes "pinned", because the heap is
never compacted and all addresses are absolute.

Arrays that exceed a certain size (85Kb currently), are moved to the
Large Object Heap, but they aren't pinned by this. The LOH is not
compacted, but that doesn't mean that the objects cannot get
collected.

All objects on the LOH are pinned at all times, by the nature of the heap (non-compacting).


This is not what pinned means in this context. The objects on the LOH (all version of the CLR) are at a fixed address for their life time, but that doesn't mean they are pinned. Pinning is an explicit action that allocated an Object Handle and stores it in the GCHandles table and set's the "pinned" bit (don't know exactly where this bit is set as this changes from one release to another).
If you want to see pinning in action you'll have to run your code in a native debugger and load sos.
For instance consider following snip:

...
double[] a2 = new double[20000];
a2[a2.Length-1]= 0.7889;
// Break here and watch the Handles table, using !sos.gchandles
GCHandle h = GCHandle.Alloc(soa, GCHandleType.Pinned);
// break again and watch the handles table again, you will see
// 1) the: Pinned Handles: value that was incremented
// 2) and object reference is added to the table, object reference which is pointing to the actual array object.
...
The same thing happens when "PInvoking", but now the pinning is only done when the GC kicks in. Note that you need to explicitly pin when passing a buffer (or callback) to unmanaged when there is a chance that your buffer gets accessed after the call returned. Do you know exactly what gets done in the unmanaged function? You better do!, the function can kick off another thread pass the address of the buffer and return. The object passed-in is no longer protected when the GC comes along, the thread that accesses the object is subject to AV exceptions!


It would be useful to request that a particular buffer not be subject to relocation by the GC. Probably the easiest way to do this would be to place it in the LOH. The OLE task allocator or HGlobal allocator, both of which are already exposed by the Marshal class in a typeless way, would be other options. It could be as simple as adding a T[] Marshal.AllocCoTaskMem<T>(int elementCount) override.

But now you are allocating from the unmanaged heap (COM heap or CRT heap or whatever). So now you will incur the costs of copying back and forth, again this depends on the semantics, but might be a solution when you need to pass large data chunks to unmanaged land.


Willy.



.



Relevant Pages

  • Re: unmanaged vs managed.
    ... Above article is based on what is found in SSCLI and does not reveal that much about the CLR memory manager's internals, nor does it include anything really useful about the GC and the JIT implementation in the commercial CLR product. ... Note that in following I denote by *Heap*, the "Heap Managers" heap, while with *GC-Heap* I denote the CLR managed heap. ... It's quite obvious that the CLR has it's own memory manager, after all the *GC-Heap* is THE CLR's private heap, no other component in the system uses/manages the GC-Heap but the CLR. ... The CLR Object Manager allocates from the GC-Heap, while the GC keeps the GC-Heap "clean" in close cooperation with the CLR Memory Allocator or an external Memory allocator like the one used when you run the CLR in the SQL Host. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: unmanaged vs managed.
    ... JIT implementation in the commercial CLR product. ... while with *GC-Heap* I denote the CLR managed heap. ... *GC-Heap* is THE CLR's private heap, no other component in the system ... Allocator or an external Memory allocator like the one used when you run ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: The Hoard Scalable Memory Allocator
    ... allocator in every thread (e.g., ms heap w/ HEAP_NO_SERIALIZE). ... The stack goes bye-bye when its parent ... There are case in which you don't control the creation and destruction ...
    (comp.programming.threads)
  • Re: delete does not free memory with CString
    ... The default heap does not return space to the OS. ... Does CString use a "custom allocator"? ... There is a hook for using a custom allocator, ... what's actually going on inside the windows heap, so the OP might be misled ...
    (microsoft.public.vc.mfc)
  • Re: alloca / _alloca / dynamic stack memory
    ... can't comment inline. ... locking allocator or you could use a standard cheap mutex. ... Thread local storage isn't the same as an internally unsynchronized heap. ... require fragile inline assembly hacking dependent on the exact stack ...
    (microsoft.public.vc.language)

Loading