Как я знаю, что массив структур был выделен в куче больших объектов (LOH) в .NET? - PullRequest
0 голосов
/ 06 мая 2010

После некоторых экспериментов с использованием CLR Profiler я обнаружил, что:

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;
    }

Как во время выполнения узнать, как массив структур (или любой массив) был выделен в куче больших объектов (LOH)?

Ответы [ 3 ]

2 голосов
/ 06 мая 2010

Любой объект размером более 85 000 байт будет сохранен в LOH. Вот отличный пост в блоге о .Net Memory Management .

1 голос
/ 27 января 2011

Вы можете узнать сразу после выделения. Используйте перегрузку GC.GetGeneration (object), чтобы получить номер поколения, в котором находится объект. Для LOH это будет 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

Обратите внимание, что это имеет некоторые ограничения и никоим образом не является подходящим способом для производственного кода, я предполагаю: если вы запрашиваете это число позднее, объект может быть уже перемещен из поколения 0 в поколение 2 Я не знаю, как различить кучу Gen2 (маленький объект) и LOH. Кроме того, число, возвращаемое для объектов в LOH, равно 2 для всех версий .NET, с которыми я его тестировал. Но я не смог найти это в реальной спецификации, так что это может быть также вопросом изменения.

1 голос
/ 06 мая 2010

Из ваших комментариев я не думаю, что вам на самом деле нужно знать, будет объект на LOH или нет. Является ли это фактической причиной замедления работы вашего приложения, не имеет значения, когда все, что вы действительно хотите сделать, это отображать предупреждение пользователю, когда он вводит значение, которое «слишком велико».

Поэтому я бы предложил кое-что попроще: просто используйте метод проб и ошибок, чтобы определить значение отсечения. Если они введут размер, превышающий значение проб и ошибок, отобразите предупреждение.

Что касается ваших реальных проблем с производительностью, вместо выделения одного большого двумерного массива вы можете просто выделить группу «меньших» одномерных массивов. Вместо:

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

Вы бы сделали это:

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
}

У вас все равно будет одинаковое количество узлов, но на LOH ничего не будет. Лично я думаю, что вы, вероятно, обнаружите, что производительность на самом деле не сильно отличается, но, возможно, стоит просто попробовать.

...