views:

88

answers:

3

Is there a way to tell the .NET to allocate a new object in generation 2 heap. I have a problem where I need to allocate approximately 200 MB of objects, do something with them, and throw them away. What happens here is that all the data gets copied two times (from gen0 to gen1 and then from gen1 to gen2).

A: 

Framework works differently with big objects that with the normal objects. So briefly it put big objects in generation and don't move it when reallocate heap.

pocheptsov
+2  A: 

There is no way to allocate directly in generation 2. All allocations happen in generation 0 and for large objects on the LOH.

However, data is generally not copied when objects move to a new generation. Instead the start points of the different heaps are moved. The objects may be moved due to compaction of the heap, but that is a different story.

If it is important to store objects in generation 2, you could reuse the instances. I.e. make some init method on the types and call this instead of creating new instances.

Brian Rasmussen
If I understand correctly, all newly created objects are allocated in gen0 heap. When gen0 heap is full, all the objects (that are still needed) are moved to gen1, and gen0 becomes empty. The same happens to gen1 when GC of gen1 is run. As far as I know, there is no such thing to moving pointers to different heaps. Maybe you can give a link to MSDN or somewhere, because what i'm experiencing is alot of copying (which can be seen with Performance Monitor).
nimoraca
@nimoraca: The moving the pointer part is what the CLR does. If it didn't you would have to move objects for all collects, which would be very inefficient. Check out the book CLR via C# for details. This article has some of the same points http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
Brian Rasmussen
@nimoraca: If you're interested in the details, you can also inspect the different heaps etc using WinDbg and SOS (or PSSCOR2).
Brian Rasmussen
Since LOH objects are the ones larger than 85k (or something like that) I did a simple test. First I created 1000 byte arrays of size 50kb. Since these objects are not allocated in LOH, then I created 500 byte arrays of size 100kb. The second test was almost three times faster than the first one, which clearly illustrates the problem of moving objects around between generations. This is the main performance problem in my application, because it tends to allocate a lot of small objects very often. What I will try is to reuse objects (as you suggested), but I was hoping for an easier solution.
nimoraca
Actually the LOH is not compacted, so objects are not moved during GC of the LOH. It is hard to comment on your measurements without the details.
Brian Rasmussen
Yeah he's aware that LOH is not compacted, that's why the second test is faster than the first one, because no compacting occurs.
Ivan
@Ivan: But is it more complicated than that. Allocation on the generational heap is really fast unless it triggers a collection. It is just advancing a pointer. Allocation on the LOH may be much slower as it employs a free list which must be searched.
Brian Rasmussen
A: 

If you want to fix your objects so the framework cannot move them, you can try using GCHandle to pin the objects. This is usually used for P/Invoke but will give the result you're looking for. I have my doubts that you're seeing slowdowns due to generational compaction but I can't say without seeing your profiling data.

http://msdn.microsoft.com/en-us/library/khk3k17t%28v=VS.71%29.aspx

Example:

var q = new MyObject();
var handle = GCHandle.Alloc(q, GCHandleType.Pinned);

// use object

handle.Free();
Ron Warholic