Что делать, если сборка мусора .Net выполняется медленнее, чем скорость создания / удаления объектов?

У меня есть живой индекс Lucene, который обновляется в течение дня. Когда поступает несколько последовательных пакетов обновлений для индекса, я хочу, чтобы эти обновления были доступны для поиска как можно быстрее. Поэтому мне нужно воссоздать IndexSearcher.

Проблема в том, что IndexSearcher может занимать около 100 МБ памяти, и когда поступает много обновлений, его можно воссоздавать относительно часто, и я заметил, что сборщик мусора .Net медленно очищает ссылку на старый объект IndexSearcher. . Это приводит к тому, что использование памяти процессом выходит из-под контроля, поскольку сборщик, кажется, освобождает память от старых IndexSearcher медленнее, чем они воссоздаются.

Я обнаружил, что эта проблема решается путем перехода границы на запретную территорию и вызова GC.Collect(), который немедленно освобождает память. Влияние на производительность не кажется заметным, но поскольку я делаю то, против чего многие советуют, мне было бы любопытно, есть ли у кого-нибудь еще опыт создания и выпуска объектов быстрее, чем их очищает сборщик мусора. Мне было бы особенно интересно, если бы у кого-нибудь была эта проблема с Lucene IndexSearcher.

Я должен отметить, что IndexSearcher воссоздается в часы пик примерно раз в 10-20 секунд.


person Nathan Ridley    schedule 27.07.2011    source источник
comment
Звуки indexSearcher - это своего рода кеш. Пожалуйста, не забывайте, это плохой способ использовать кеш при частом обновлении ...   -  person Alberto León    schedule 27.07.2011
comment
Нет, это не кешируется. Я использую один поисковик, и он хранится в его собственном частном поле. Когда я воссоздаю его, я просто устанавливаю в поле только что созданный экземпляр. Затем старая ссылка удаляется и становится доступной для сбора.   -  person Nathan Ridley    schedule 27.07.2011
comment
У меня была аналогичная проблема в прошлом. Хранение таблиц данных в сессиях. Новые объекты растут быстрее, чем собранный сборщик мусора. Вам нужно, чтобы объекты и его свойства в коллекции indexSearcher не упоминались в долгоживущих объектах. Убедитесь, что никакие другие объекты не ссылаются на старый indexSearcher. Если на какой-либо из объектов в indexSearcher есть ссылка в другом, старый indexSearcher считается объектом с длительным сроком действия и будет собираться во втором или третьем поколении GC, а не в gen0, который вам нужен.   -  person Alberto León    schedule 27.07.2011
comment
Да, старый поисковик нигде не упоминается после того, как я воссоздал его, так что он, очевидно, считается долгоживущим.   -  person Nathan Ridley    schedule 27.07.2011
comment
вы используете последнюю версию lucene? Если да, можете ли вы опубликовать тестовый пример, в котором воспроизводится проблема? Я не могу воспроизвести поведение, которое вы наблюдаете в последней версии lucene. Я использую индекс 100 ГБ. Я добавляю 100 документов, получаю поисковик, выполняю 50 случайных поисков. Я повторил этот процесс в цикле 100 000 раз, и мое приложение по-прежнему занимает 275 МБ оперативной памяти.   -  person Jf Beaulac    schedule 28.07.2011
comment
@JfBeaulac - Я использую Lucene.net, что в настоящее время приравнивается к Lucene 2.9.2. Также в моем индексе сейчас 2,8 миллиона документов, а когда он будет запущен, он увеличится до 200 миллионов +.   -  person Nathan Ridley    schedule 28.07.2011


Ответы (2)


Я считаю приемлемым называть GC.Collect, если вы только что освободили тонну памяти , а память можно и нужно освободить сейчас, чтобы уменьшить нагрузку на память. GC не знает, что эта память теперь доступна, пока не запустится снова, и вы не знаете, когда это будет.

В вашем случае вы сказали, что «его можно воссоздавать относительно часто». Если это так, то вызов GC.Collect при воссоздании звучит разумно.

person Paul Williams    schedule 27.07.2011
comment
Спасибо за поддержку - меня всегда пугает то, что я пишу плохой код, когда работаю с областями, которые не знаю наизнанку! - person Nathan Ridley; 27.07.2011
comment
+1 Я согласен с мнением, что это нормально там, где оказалось полезным. Но в большинстве случаев это бесполезно по сравнению с обычным поведением GC, поэтому на него все время смотрят подозрительно. - person Adam Houldsworth; 27.07.2011