Как узнать, что массив структур был размещен в куче больших объектов (LOH) в .NET?

После некоторых экспериментов с использованием 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)?


person AMissico    schedule 06.05.2010    source источник
comment
Я не верю, что это возможно (без использования самого API профилирования). Почему ты хочешь знать?   -  person Dean Harding    schedule 06.05.2010
comment
У меня проблемы с производительностью из-за одной структуры, используемой приложением. Я успешно оптимизировал другие массивы (stackoverflow.com/questions/2762424/). Тем не менее, эта структура является настоящим убийцей производительности.   -  person AMissico    schedule 06.05.2010
comment
Если это просто для настройки производительности, то почему бы просто не использовать профилировщик, как раньше?   -  person Dean Harding    schedule 06.05.2010


Ответы (3)


Любой объект размером более 85 000 байт будет храниться в LOH. Вот отличное сообщение в блоге о . Управление сетевой памятью.

person Matt Dearing    schedule 06.05.2010
comment
для double [] ограничение в настоящее время (.NET RT 4.0) составляет 8k - person user492238; 28.01.2011

Судя по вашим комментариям, я не думаю, что вам действительно нужно знать, будет ли объект перемещаться в 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 ничего не будет. Лично я думаю, вы, вероятно, обнаружите, что производительность на самом деле не будет сильно отличаться, но, возможно, стоит просто попробовать.

person Dean Harding    schedule 06.05.2010

Вы сможете узнать сразу после выделения. Используйте перегрузку 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

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

person user492238    schedule 27.01.2011
comment
+1 за новаторское мышление. Хороший. Умная. То, о чем я должен был подумать. Я попробую позже. - person AMissico; 27.01.2011
comment
@AMissico: спасибо! приятно знать, тебе нравится (даже если +1 не пришло;)) - person user492238; 28.01.2011
comment
@ user492238: Когда я проверю ваш ответ, вы получите реальный голос. : O) - person AMissico; 28.01.2011
comment
@AMissico: ну, я не буду об этом умолять;) но обычно «+1» означает просто голосование. Когда ответ может быть проверен, это скорее квалифицирует его как правильное решение :) - person user492238; 28.01.2011