Размер кучи .NET поколения 0 - PullRequest
15 голосов
/ 07 мая 2009

Можно ли установить минимальный размер кучи поколения 0 в .NET?

У меня есть следующая связь. У меня есть функция, которая выделяет около 20-30 МБ объектов размером 1 КБ, что-то с ними делает и завершает работу, оставляя все выделенные объекты для GC-редактирования. Теперь в Performance Monitor я вижу, что размер кучи поколения 0 составляет 5-6 МБ, что недостаточно для приема всех необходимых мне 20-30 МБ объектов. Когда я начинаю выделять, в какой-то момент запускается gen0 GC, и поскольку все объекты нужны, он переводит их в gen1. В следующий раз, когда GC начнет работать, эти объекты будут продвинуты в gen2. Наконец, около 15 МБ моих объектов попадают в кучу gen2. По моей логике это временные объекты, которые никоим образом не должны попадать в кучу gen2. Я считаю, что проблема в размере кучи gen0. Но я не уверен. Я знаю, что в Java есть возможность установить минимальный размер кучи поколений. Есть ли такой способ в .NET?

Ответы [ 7 ]

8 голосов
/ 07 мая 2009

Размер разных поколений - это деталь реализации, и я не знаю ни одного способа настроить его для приложений .NET. Если память мне не изменяет, поколение 0 и 1 совместно используют один сегмент, а в Win32 - 16 МБ, поэтому, если вы создадите много объектов, некоторые из них будут преобразованы в более высокие поколения, если на них все еще есть ссылки ты опиши)

Я предполагаю, что идея ограничения размера поколения 0 состоит в том, чтобы коллекция g0 была дешевой. Если поколение 0 может вырасти до любого размера, ваша общая производительность, скорее всего, пострадает.

РЕДАКТИРОВАТЬ: Я считаю, что книга Джеффри Рихтера имеет некоторые подробности об этом, так что вы можете проверить это.

EDIT2: Рихтер заявляет (стр. 502-507), что начальный бюджет поколения 0 составляет 256 КБ, а первоначальный бюджет поколения 1 - 2 МБ. Однако это не размер поколения. Бюджеты корректируются по мере необходимости и будут увеличиваться и уменьшаться в зависимости от использования памяти приложением.

Однако в .NET Framework 2.0 от Joe Duffy утверждается, что поколения поколений (т.е. поколения 0 и 1) разделяют один сегмент, который обычно составляет 16 МБ (стр. 117). Только поколению 2 разрешено расти по мере необходимости (я предполагаю, что LOH также может расти по мере необходимости, но это не ясно из текста).

3 голосов
/ 07 мая 2009

Спасибо, ребята, за вашу помощь.

Whell, ситуация очень интересная. Я никогда не упоминал, что я храню эти 30 МБ объектов в массиве, размер которого составляет 100000. Сначала я выделяю этот массив, а затем заполняю его объектами. Поскольку этот массив больше 85 КБ, он сохраняется в куче больших объектов. Оказывается, чтобы сборщик мусора собирал объекты в этой куче, он должен запустить сборщик gen2, поэтому каждый раз, когда в куче больших объектов не хватает места, он запускает сборщик gen2, который снижает производительность. Вот простой пример, который будет постоянно называть коллекцию gen2. Вам нужно запустить его в режиме отладки (из-за оптимизации компилятора).

static void Main(string[] args)
{
     while (true)
     {
         byte[] objects = new byte[100000];
     }
}

Означает ли это, что всякий раз, когда мне нужен временный массив, размер которого превышает 85 КБ, этот массив попадает в кучу объектов larget?

3 голосов
/ 07 мая 2009

Куча поколения 0 изначально имеет размер кеша вашего процессора. Это связано с тем, что небольшие временные объекты даже не нужно перемещать в основную память.

3 голосов
/ 07 мая 2009

Вы уверены, что больше не ссылаетесь на эти объекты? GC очень хорош в настройке себя под нужды вашего приложения и не будет продвигать объекты до поколения 2, если у вас где-то нет корней для этих объектов.

Я думаю, что если вы выясните, где находятся эти корни, и убедитесь, что вы больше нигде не ссылаетесь на эти объекты, то ГХ начнет освобождать память для этих объектов и никогда не переводить их в поколение 1, не говоря уже о поколение 2. Также, если если вы сделаете это, то GC обнаружит, что вам нужно поколение 0, чтобы оно было больше, и увеличит размер кучи от вашего имени.

2 голосов
/ 29 октября 2009

В первом поколении0 могут увеличиваться и уменьшаться, но это в будущем. когда процесс запускается, инициализированная управляемая куча имеет фиксированный размер в поколении 0 256 КБ (что означало Рихтера), поскольку современные компьютеры имеют 256 и более памяти для ресурсов ЦП 2-го уровня. Во-вторых. Андрей, ты прав. Когда какой-то объект настолько велик, он сразу переходит в gen2. Я могу предположить, что вы хотели уменьшить размер gen0, чтобы чаще вызывать GC, чтобы очистить неиспользуемое пространство и сделать ваше приложение легче. У меня такая же проблема на сайте SilverLight и поиск решения. Я думаю, что если код создает много объектов, имеющих корни, и когда gen0 заполнен, CLR вызывает GC, которые перемещают их в gen1, а затем, когда объекты растут, перемещают их в gen2. Допустим, все 3 поколения почти заполнены. Затем, например, GC позвонил. Что это будет делать Просто ясно, поколение0? Как с 1-м и 2-м. Я думаю, что решение, чтобы сохранить свет памяти заключается в следующем. Сначала создайте маленькие и большие объекты вместо больших по размеру и меньшего количества. Внутренние ссылки на вторые объекты должны быть односторонними, а не хаотическими. Статические объекты, которые не создаются динамически, например, в соответствии с поступающими записями из базы данных, должны храниться в глобальных переменных и не создаваться снова, когда код вызывает их.

1 голос
/ 07 мая 2009

+ 1 к Андрею. GC самонастраивается , он узнает о шаблонах потребности приложения в памяти на лету.
В вашем случае, если GC выполняет коллекцию Gen 0 и обнаруживает, что сохранилось много объектов / не было использовано много памяти, сборщик мусора автоматически увеличит бюджет / квоту Gen 0.

Глядя на членов типа GC , похоже, не существует способа программной настройки бюджетов / размеров GC Generation.

0 голосов
/ 07 мая 2009

Я не думаю, что есть возможность установить эти значения в .NET GC.

На первый взгляд, похоже, что эта конкретная ситуация оправдывает необходимость иметь такие расширенные опции, но если это будет опция static , это повлияет на всю вашу жизнь программа. Опция dynamic , которую вы можете установить во время выполнения, была бы идеальной.

Кроме того, я не думаю, что это сильно повлияет на производительность вашей программы, хотя, если вы сможете увеличить размер gen (0), вы можете освободить часть памяти (и получить некоторую производительность) ,

Поскольку ГХ самонастраивается, gen (0) автоматически увеличивает размер, и объекты BIG рано или поздно будут собираться мусором.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...