Использование кеширующей памяти XmlDocument - PullRequest
2 голосов
/ 06 апреля 2010

Мы наблюдаем очень высокое использование памяти в веб-приложениях .NET, которые используют XmlDocument.Небольшой (~ 5 МБ) XML-документ загружается в объект XmlDocument и сохраняется в HttpContext.Cache для удобного запроса и преобразования XSLT при каждой загрузке страницы.XML периодически модифицируется на диске, поэтому кэш зависит от файла.

Такое приложение использует сотни мегабайт оперативной памяти.

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

У кого-нибудь есть какие-либо предложения относительно того, как мы можем достичь той же цели, но с меньшим использованием ОЗУ?

Ответы [ 2 ]

5 голосов
/ 06 апреля 2010

Мои два цента. , .

Я бы беспокоился, если бы использование памяти было экспоненциальным в зависимости от размера XML-документа. например Память XML-файла объемом 1 МБ устанавливается на уровне 10 МБ, 2 МБ выравнивается на 30 МБ и т. Д.

Кроме того, учитывайте стоимость XML-файла не столько по размеру байта, сколько по стоимости каждого узла. Если в вашем 5-мегабайтном XML-документе, скажем, два узла данных, то представление документа в памяти не будет намного больше, чем 5 мегабайт (на самом деле это может быть гораздо меньше, учитывая, что двоичные данные в XML будут в два раза больше, чем в память).

* Если ваш XML-документ имеет формат utf-8, и у вас есть два больших текстовых узла, тогда представление в памяти может составлять 10 МБ (текст может храниться в строках .net, которые являются Unicode, и будет быть вдвое больше ширины стандартного текста на английском языке UTF-8).

Если документ XML состоит из множества дискретных строковых значений, то каждый узел является объектом, каждое имя узла является объектом, каждое значение узла является объектом. Таким образом, при условии, что ссылки имеют размер 4 байта, это (как минимум) дополнительные 12 байтов на узел.

Теперь, если у вас много узлов и средняя длина имени узла + значение равно 20 символам, тогда накладные расходы для файла 5 МБ составляют 3 МБ, плюс дополнительные 100% для utf-8 для Unicode для преобразования требуется 5 МБ + 5 МБ + 3 МБ (как минимум) = 13 МБ (как минимум) ОЗУ для хранения XML-файла объемом 5 МБ. , , и это не считая байтов, потерянных для выравнивания памяти, или дополнительных байтов, используемых для хранения размера каждого строкового объекта **.

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

См. Когда Рико Мариани вызывает GC.Collect () для ситуаций, когда не только нормально вызывать GC Collect, но и когда это необходимо.

Надеюсь, это поможет, извините, если я проповедую хору об объеме памяти.

* Я не знаю, так ли это на самом деле, но был бы удивлен, если это не так.
** Я предполагаю, что строки .net хранят размер строки до / после фактических символов строки, это может значительно увеличить представление в памяти на дополнительные 4-8 байт на узел, что дает стоимость 20 байт. на 20 байтов имени узла / значения. Что эффективно увеличивает накладные расходы в соответствии с размером хранимых данных.

1 голос
/ 06 апреля 2010

Так как агрессивный GCing очищает вещи, вы должны искать места, где вы не можете утилизировать объекты, которые реализуют IDisposable. Возможно, вам нужно посмотреть на свой код с помощью XSL-преобразования, чтобы убедиться, что используемые там объекты правильно расположены.

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