Re: Garbage collectable pinned arrays!
"Ben Voigt [C++ MVP]" <rbv@nospam.nos pamwrote in message
news:%23AkPUVmb IHA.1164@TK2MSF TNGP02.phx.gbl. ..
>>
>True, but if you need this, why is the cost of pinning so important?
>The cost of GCHandle.Alloc is ~5500 cycles. That means a one time
>cost to pin a buffer that lives until the end of the process, if you
>do this early in the process you won't suffer from fragmentation of
>the gen0 heap as this object will end on the gen2 heap anyway.
>
That's what I do now.
>
But doesn't the object need to be moved to end up in gen2 data space?
Won't the pinning reference prevent that?
>
No, but all depends on the sizes of the individual generations, that's why I
say pin your buffers early in the process and after a GC.Collect().
You can verify the location of your pinned buffer, by attaching to a native
debugger like nsdb or windbg..
Once attached, enter:
!dumpheap -type <yourPinnedType >
this returns the object's address (and some other info), something like:
....
Address MT Size
02721660 79131a68 1612
....
To find the generation where your object "lives" , you'll have to compare
it's address with the start address of the generations returned by:
!eeheap -gc
....
Number of GC Heaps: 1
generation 0 starts at 0x0272d230
generation 1 starts at 0x02721cac
generation 2 starts at 0x02721000
....
here the object at address 02721660 falls in the Gen2 range.
Pinning an object that follows a couple of MB's of other live objects, has
little chance to end on the Gen2, unless the GC can move the object to gen2
at the moment of "pinning".
>
But it needs an "unsafe" block, for no apparent reason.
"unsafe" blocks are needed when using pointers!
This produces non-verifiable code, so no surprises here, you are warned.....
Willy.
"Ben Voigt [C++ MVP]" <rbv@nospam.nos pamwrote in message
news:%23AkPUVmb IHA.1164@TK2MSF TNGP02.phx.gbl. ..
>>That's not an unusual case. I've already given two examples of APIs
>>in widespread use which require a buffer to stay in one position
>>after the initial function call which accepts the pointer.
>>>
>>in widespread use which require a buffer to stay in one position
>>after the initial function call which accepts the pointer.
>>>
>True, but if you need this, why is the cost of pinning so important?
>The cost of GCHandle.Alloc is ~5500 cycles. That means a one time
>cost to pin a buffer that lives until the end of the process, if you
>do this early in the process you won't suffer from fragmentation of
>the gen0 heap as this object will end on the gen2 heap anyway.
That's what I do now.
>
But doesn't the object need to be moved to end up in gen2 data space?
Won't the pinning reference prevent that?
>
say pin your buffers early in the process and after a GC.Collect().
You can verify the location of your pinned buffer, by attaching to a native
debugger like nsdb or windbg..
Once attached, enter:
!dumpheap -type <yourPinnedType >
this returns the object's address (and some other info), something like:
....
Address MT Size
02721660 79131a68 1612
....
To find the generation where your object "lives" , you'll have to compare
it's address with the start address of the generations returned by:
!eeheap -gc
....
Number of GC Heaps: 1
generation 0 starts at 0x0272d230
generation 1 starts at 0x02721cac
generation 2 starts at 0x02721000
....
here the object at address 02721660 falls in the Gen2 range.
Pinning an object that follows a couple of MB's of other live objects, has
little chance to end on the Gen2, unless the GC can move the object to gen2
at the moment of "pinning".
>>
>>
>>
>But , this is what "fixed" is meant for, sure, it's scope is limited
>by it's containing function scope, but you can perfectly pin an
>object across several unmanaged function calls.
>>
>>>Also, you keep ignoring my remark that the fact that addresses of
>>>*Large* objects are fixed is a convenience of the current version of
>>>the CLR, nothing stops MS from changing this.
>>>
>>Which is why the OP is asking for a keyword / MSIL flag that will
>>let the runtime know that the object is intended to be fixed for as
>>long as it lives. It would be an implementation detail whether the
>>memory is allocated from the LOH, OLE task allocator, etc, etc. Also I
>>don't think that sacrificing GC for such objects would
>>necessarily be a big loss, they either will live to the end of the
>>process anyway, or they can be explicitly freed.
>>>
>>>*Large* objects are fixed is a convenience of the current version of
>>>the CLR, nothing stops MS from changing this.
>>>
>>Which is why the OP is asking for a keyword / MSIL flag that will
>>let the runtime know that the object is intended to be fixed for as
>>long as it lives. It would be an implementation detail whether the
>>memory is allocated from the LOH, OLE task allocator, etc, etc. Also I
>>don't think that sacrificing GC for such objects would
>>necessarily be a big loss, they either will live to the end of the
>>process anyway, or they can be explicitly freed.
>>>
>But , this is what "fixed" is meant for, sure, it's scope is limited
>by it's containing function scope, but you can perfectly pin an
>object across several unmanaged function calls.
But it needs an "unsafe" block, for no apparent reason.
This produces non-verifiable code, so no surprises here, you are warned.....
Willy.
Comment