AMissico
AMissico

Reputation: 21684

How do I know an array of structures was allocated in the Large Object Heap (LOH) in .NET?

After some experimenation using CLR Profiler, I found that:

Node[,] n = new Node[100,23]; //'84,028 bytes, is not placed in LOH
Node[,] n = new Node[100,24]; //'86,428 bytes, is 

    public struct Node {
        public int Value;
        public Point Point;
        public Color Color;
        public bool Handled;
        public Object Tag;
    }

During run-time, how do I know an array of structures (or any array) was allocated in the Large Object Heap (LOH)?

Upvotes: 0

Views: 388

Answers (3)

user492238
user492238

Reputation: 4084

You can find out right after allocation. Use the GC.GetGeneration(object) overload to get the generation number, the object lays in. For LOH this will be 2.

Node[,] n = new Node[100,23]; 
// GC.GetGeneration(n) should give 0
Node[,] n = new Node[100,24]; 
// GC.GetGeneration(n) should give 2

Note, this comes with some restrictions and is by no means a proper way for production code, I assume: If you query that number at a later point, the object may has been moved from Gen 0 up to Gen 2 already. There is no way I know of to distinguish between the Gen2 (small object) heap and LOH. Also, the number returned for objects on the LOH is 2 for all .NET versions I did test it with. But I couldn't find this in a real specification, so it may be a matter of change as well.

Upvotes: 2

Dean Harding
Dean Harding

Reputation: 72668

From your comments, I don't think you actually need to know whether the object is going to go on the LOH or not. Whether or not that's the actual cause of your application's slowdown is kind of irrelevant when all you really want to do is display a warning to the user when they enter a value that's "too big".

So I would suggest something a bit simpler: just use a bit of trial-and-error to determine the cut-off value. If they enter a size over your trial-and-error value, display the warning.

As for your actual performance problems, instead of allocating one big two-dimensional array, you could simply allocate a bunch of "smaller" one dimensional arrays. Instead of:

Node[,] n = new Node[100,100]; // this will go the LOH

You'd do this:

Node[][] n = new Node[100][];
for(int i = 0; i < n.Length; i++) {
    n[i] = new Node[100];  // none of these will be on the LOH
}

You'd still have the same number of nodes in total, but nothing would go on the LOH. Personally, I think you will probably find that the performance is actually not going to be all that much different, but it might be worthwhile to just give it a try.

Upvotes: 1

Matt Dearing
Matt Dearing

Reputation: 9386

Any object larger than 85,000 bytes will be stored on the LOH. Here is a great blog post about .Net Memory Management.

Upvotes: 2

Related Questions