Применение утечки строк? - PullRequest
1 голос
/ 11 мая 2010

Мое приложение .net выполняет тяжелую загрузку / манипулирование строками и, к сожалению, 1002 * потребление памяти продолжает расти и расти, и, глядя на него с помощью профилировщика, я вижу множество невыпущенных экземпляров строк.Теперь в тот или иной момент мне нужны все объекты, которые имеют эти строковые поля, но когда я это сделаю, я могу избавиться, например, от половины этого, и я Dispose () и установлю экземпляры в null, но в GarbageCollector не может подобрать это .. они остаются в памяти (даже через полчаса после утилизации и т. Д.).

Теперь, как мне правильно избавиться от ненужных строк / экземпляров объектов вчтобы освободить их?

На них больше не ссылаются (afaik), но, например, профилировщик памяти aspose говорит, что их расстояние до корня gc равно '3'?

Update :Исходные строки поступают из экземпляра взаимодействия.Возможно ли, что это приводит к утечкам?

Как и при ... присваивании

myClass.StringProperty = interopInstance.Description.Text;

.. мой .StringProperty по-прежнему имеет ссылку на это взаимодействие и, следовательно, "протекает" /оставить interopInstance не собранным и не соответствующим образом освобожденным / не маршалированным?

Ответы [ 3 ]

3 голосов
/ 11 мая 2010

Установка частного поля на null может быть полезна, когда класс, содержащий это поле, все еще будет использоваться. Это позволит собирать указанный объект. Однако, когда на этот экземпляр этого частного поля нет ссылок, то будет и объект, на который он ссылается. Другими словами, бесполезно обнулять закрытые поля в объекте, на который скоро не ссылаются.

Я думаю, что у вас нет утечки приложений. Возможно, вы создаете строки, которые хранятся в куче больших объектов (LOH). Объекты хранятся в LOH, если они больше или равны 85000 байтов (с 42492 символами или более). LOH собирается только тогда, когда происходит полный сбор мусора (поколение 2). Поэтому, поскольку у вас, похоже, нет никаких OutOfMemoryExceptions, я не думаю, что есть утечка. Вашему приложению просто не хватает памяти, а GC просто не собирает Gen2.

Вы можете проверить это, позвонив по номеру GC.Collect(). Это удалит все неиспользуемые крупные объекты.

<ч />

Таким образом, хотя в вашем приложении, вероятно, нет утечки, объем памяти может быть нежелательным большим. Особенно, когда вы пишете настольное приложение, которое не является единственным приложением, запрашивающим память. Помимо этого, большая куча памяти также может вызвать проблемы с производительностью, потому что GC должен работать чаще.

Возможно, возможно реорганизовать ваш код так, чтобы он занимал меньше памяти. Например, использование StringBuilder объектов (если вы этого еще не сделали). Или, может быть, даже кэшировать StringBuilder объекты в пуле и использовать их вместо создания нового. Особенно при установке свойства Capacity при использовании экземпляра, полученного из пула. Это может быть особенно полезно, потому что LOH имеет тенденцию легко фрагментироваться, что может вызвать OutOfMemoryExceptions. Между прочим, это проблема только в 32-битных системах, поскольку 64-битные системы имеют практически неограниченное виртуальное адресное пространство. В ближайшие годы 64-битная среда станет все более популярной, и я полагаю, что Microsoft не вкладывала средства в решение этой проблемы в 32-битных версиях CLR.

Обновление В случае взаимодействия строки сериализуются и десериализуются. Строка передается в виде байтового массива, поэтому в общем случае она не изменяется, сохраняя ссылки. Однако каждый раз, когда вы извлекаете строку из взаимодействия, создается новый байтовый массив, и в .NET этот byte [] копируется в строку. Это удвоит объем используемой памяти.

1 голос
/ 11 мая 2010

Просто понаблюдаю за этим, но ты объединяешь много строк? Если да, то используете ли вы оператор «+» для этого? Строка является неизменной, это означает, что вы можете создавать новый строковый объект в памяти каждый раз, когда вы над ним работаете.

Если вы объединяете строки, вам следует рассмотреть возможность использования объекта StringBuilder (если вы этого еще не делаете) или даже метода String.Concat (). Это может быть проблемой, особенно если вы объединяете строки в цикле в любой точке.

0 голосов
/ 14 мая 2010

Я работал над системой передачи данных между многими терминалами. Эти терминалы генерируют текстовые данные (в формате XML), которые затем сжимаются и передаются на другие терминалы. Первоначально мы сталкивались с той же самой проблемой, с которой вы сталкиваетесь, когда приложение использует все больше и больше оперативной памяти и, в конечном итоге, исчерпывает память. Скорость, с которой оно работало, экспоненциально возрастала, когда к нему подключалось больше терминалов.

Производительность этой системы не была самой важной функцией, но долгое время безотказной работы было.

После того, как мы просмотрели профилировщики, чтобы найти, куда исчезает наша память, мы обнаружили, что наши строки оказались в LOH, если в них было что-то существенное.

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

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

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