2012-02-01 3 views
1

Я запускаю много потоков одновременно, каждый из которых записывает/считывает данные в/из очереди; Данные разворачиваются постепенно, пока они обрабатываются и сохраняются в БД. По какой-то причине память не освобождена, хотя очереди пусты, и я убедился, что вся подписка на события между устройством чтения данных и процессором данных не подписана в конце потоков. Количество присаженных ОЗУ Точно количество данных, которое считывается двоичными считывателями и помещается в очереди.Память не освобождается приложением до тех пор, пока GC не будет явно вызвана

Чтобы изолировать проблему, я обошел процедуру «Обработка» и «Хранение базы данных».
Зачем нужно, чтобы RAM оставалась на корточках долго после завершения всех потоков, до тех пор, пока я явно не позвоню GC.Collect() или не завершаю программу? Я вручную аннулировал очередь после ее опустошения, а также аннулировал двоичный считыватель, который считывал данные. Я думал, что этого будет достаточно для того, чтобы ГК просыпаться и заниматься домашним хозяйством, по крайней мере, через несколько минут.

enter image description here

EDIT: The (переформулируется после удаления) ВОПРОС: Короче говоря, я всегда говорил, что поведение ГХ по умолчанию удалось память должным образом и что я не буду почти никогда не называть GC в явном виде, и пусть структура выполняет эту работу.
Я хотел бы знать, почему в этом случае использование памяти падает только тогда, когда явный вызов к GC.Collect

EDIT:
без GC Collect

enter image description here

С GC Collect (Вызывается на регулярной основе) enter image description here

+0

Ваша проблема может быть связана со многими вещами, не заглядывая в ваш код, довольно сложно предсказать, почему GC не использует метлу, если вы хотите, чтобы мы могли использовать VS Anywhere, чтобы просмотреть код вместе ... –

+1

Nice graph но где проблема? –

+2

Вы, кажется, довольно умный человек, который довольно анимирован, но вам нелегко оставаться на тему. Последней частью вашего поста является «Вопрос: ....», за которым следует смешное разглашение без прямого вопроса. Хотя я думаю, что вы уже вложили свой вопрос раньше в свой пост –

ответ

4

Существует три условия, когда может возникнуть сбор мусора (см. MSDN):

1.) Система имеет низкую физическую память.

2.) Память, которая используется выделенными объектами на управляемой куче , превышает допустимый порог. Это означает, что на управляемой куче превышен допустимый уровень использования памяти . Порог непрерывно регулируется по мере запуска процесса.

3.) Вызывается метод GC.Collect. Почти во всех случаях у вас нет , чтобы вызвать этот метод, потому что сборщик мусора работает непрерывно. Этот метод в основном используется для уникальных ситуаций и тестирования.

Из вашего описания это звучит как основа решила ни 1.), ни 2) является случаем, следовательно, он будет собирать только тогда, когда вы звоните GC.Collect()

+0

Благодарим вас за понимание. «приемлемый порог» - очень неопределенное понятие. Это не очень эффективно с точки зрения памяти, поскольку ограничивает объем свободной памяти, который может использоваться другими потоками (масштабируемость). –

+3

Но где говорится, что приложение вернет память в Windows? GC.Collect() только реорганизует mem внутри кучи (ов). –

+0

@MikaJacobi: Не совсем, как только другие потоки начинают выделять больше памяти в конце концов 1.) или 2.) будут вызваны вызовом GC – BrokenGlass

1

Основываясь на скриншоте, кажется, что использование памяти никогда не превышает 50% во время всего запуска приложения. Это намного быстрее.NET, чтобы оставить эту память в покое, чем останавливать ваше приложение (или, по крайней мере, занимать много процессорного времени при проверке жизнеспособности), чтобы собрать мусор. Если вы обрезаете ОЗУ вашего компьютера на 2 ГБ или около того, я уверен, что сборщик мусора активизировал бы и сохранил использование памяти в рамках аппаратных ограничений.

+0

О, да? Посмотрите на второй второй снимок экрана: –

+0

Какой из этих снимков экрана опровергает этот ответ? –

1

Кажется, что у вас есть объекты, которые вы должны использовать windbg для создания дампа, а затем используйте sos.dll для отслеживания корня для ваших объектов.

Вы можете следить за этим explanation о том, как отслеживать «корни» для ваших объектов и видеть, что вызывает эти утечки.

+0

Да, возможно, я уже это сделал и идентифицировал некоторые утечки. Но это, похоже, не связано с утечкой, поскольку вызов GC, по-видимому, освобождает память, чего не было бы, если бы была обычная утечка памяти (ну, я думаю) (см. Мой старый вопрос здесь: http: // stackoverflow.com/questions/5818802/how-to-identify-where-instances-of-an-object-are-still-referenced) –

+0

Возможно, что ваши объекты были перемещены в более высокое поколение, что также означает меньшую частоту, собираемую GC, добавление windbg и использование sos перед запуском GC.Collect() может рассказать вам о том, какое поколение они есть, и уточнить, действительно ли это то, что происходит, только один тест –

+0

также посмотреть, как используйте CLR Profiler для [Профилирования сборника мусора, собранного в .NET] (http://msdn.microsoft.com/en-gb/magazine/ee309515.aspx) –

Смежные вопросы