Какво да направите, когато събирането на .Net боклук е по-бавно от скоростта, с която обектите се създават/изтриват?

Имам жив индекс Lucene, който се актуализира през целия ден. Когато се получат няколко последователни партиди от актуализации за индекса, искам тези актуализации да бъдат достъпни за търсене възможно най-бързо. Затова трябва да пресъздам IndexSearcher.

Проблемът е, че IndexSearcher може да заеме около 100mb памет и когато преминават много актуализации, той може да бъде пресъздаван сравнително често и забелязах, че .Net garbage collector изглежда бавно за почистване на препратката към стария обект на IndexSearcher . Това води до излизане извън контрол на използването на паметта на процеса, тъй като колекторът изглежда освобождава памет от стари IndexSearchers по-бавно, отколкото те се създават отново.

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

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


person Nathan Ridley    schedule 27.07.2011    source източник
comment
Sounds indexSearcher е някакъв вид кеш. Моля, не забравяйте, че е лош начин да използвате кеша, когато актуализирате често...   -  person Alberto León    schedule 27.07.2011
comment
Не, не се кешира. Използвам един търсач и той се съхранява в собствено лично поле. Когато го пресъздавам, просто задавам полето на новосъздадено копие. След това старата препратка отпада и е достъпна за събиране.   -  person Nathan Ridley    schedule 27.07.2011
comment
Имах подобен проблем в миналото. Съхраняване на таблици с данни в сесии. Новите обекти растат по-бързо от събрания GC. Необходимо е обектите и неговите свойства в колекцията 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. Използвам 100gb индекс. Добавям 100 документа, получавам програма за търсене, правя 50 случайни търсения. Повторих този процес в цикъл 100 000 пъти и приложението ми все още е на 275MB ram.   -  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

Опитахте ли да конфигурирате събиране на боклук за сървъра? Вярвам, че се различава по това, че GC е в друга тема:

Трябва ли да използваме събиране на боклук на работна станция или събиране на боклук на сървър?

Що се отнася до „по-бързо от почистването им“, ако има налична памет, системата ще я предостави на вашия процес. Събирачът на боклук ще събира на различни кръстовища с нарастването на паметта, но няма да спре разпределенията, за да поддържа определено ниво на натиск върху паметта - операционната система управлява натиска.

За съжаление нямам пряк опит с Lucene, така че отговорът ми е само за събирането на боклук като цяло.

person Adam Houldsworth    schedule 27.07.2011
comment
+1 за линка - не знаех, че има два режима за събиране на боклука - person Nathan Ridley; 27.07.2011