четверг, 21 апреля 2016 г.

XslCompiledTransform и OutOfMemoryException

Столкнулся с проблемой, что при использовании xslt преобразований возникает Out Of Memory, если входной XML файл имеет достаточно большой объем, а приложение в ресурсах ограниченно, например по тому, что работает в 32-х разрядной системе. Под катом способы, как с этим можно бороться.

1. Отключение отладки

Если вызвать конструктор по умолчанию для XslCompiledTransform, то он автоматически включает режим записи отладочной информации. Во время отладки это может быть и полезно, но вот в работающем приложении это лишняя память. Поэтому надо пользоваться конструктором с булевым параметром и в явном виде ее отключать:

XslCompiledTransform xslt = new XslCompiledTransform(false);

2. Предварительная компиляция XSLT

Как это не странно звучит, но для того чтобы применить XSLT преобразование к XML файлу, файл содержащий это преобразование надо скомпилировать. Можно сэкономить память, если сделать это предварительно ручками.
Для этого, необходимо по пути вида:
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\
найти утилиту: xsltc.exe
и запустить ее указав какой файл с xslt преобразовать, в какую сборку и с каким именем класса записать получившийся код.
Получится что-то вида:
xsltc.exe /class:ClassName /out:OutputXSLT.dll input.xslt
Дальше все просто, подключаем сборку в проект, ну или загружаем ее во время выполнения через Reflection.
Все, теперь вместо пути к файлу, можем указать тип из нашей dll:

XslCompiledTransform xslt = new XslCompiledTransform(false);
xslt.Load(typeof(ClassName));

3. Если приходится преобразовывать много файлов одним XSLT

Во-первых, один раз создав XslCompiledTransform держим его в памяти и не пересоздаем.
Во-вторых, незабываем чистить память под поток записи результатов. Например, так:

using (XmlWriter xmlWriter = XmlWriter.Create(outputFileName))
{
    xslt.Transform(InputXmlFileName, xmlWriter);
}

4. Общее

Ну и последнее, можно попробовать собрать проект в Release конфигурации, может и на этом что-то полуситься выграть по памяти.

Комментариев нет:

Отправить комментарий