2010-05-06 2 views
0

После некоторого experimenation с помощью CLR Profiler, я обнаружил, что:Как узнать, какой массив структур был выделен в большой кучей объектов (LOH) в .NET?

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)?

+0

Я не считаю, что это возможно (без использования API профилирования). Почему ты хочешь знать? –

+0

У меня проблемы с производительностью с одной структурой, используемой приложением. Я успешно оптимизировал другие массивы (http://stackoverflow.com/questions/2762424/what-is-the-fastest-way-to-initialize-a-multi-dimensional-array-to-non-default-va/) , Тем не менее, эта структура является настоящим убийцей производительности. – AMissico

+0

Если это просто для настройки производительности, то почему бы просто не использовать профилировщик, как вы? –

ответ

2

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

+0

для double [] лимит в настоящее время (.NET RT 4.0) лежит на 8k – user492238

1

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

1

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

+0

+1 для инновационного мышления. Ницца. Умная. Что-то я должен был подумать. Я попробую позже. – AMissico

+0

@AMissico: спасибо! хорошо знать, вам нравится (даже если +1 не прибыл;)) – user492238

+0

@ user492238: вы получите фактическое голосование, когда я подтвержу ваш ответ. : O) – AMissico