Виноват ли XslCompiledTransform в медленном преобразовании XML для большого файла? - PullRequest
1 голос
/ 07 января 2010

Я очень плохо знаком с XSLT, и первое, что мне нужно сделать, - это проанализировать файл размером 300 МБ (и это на небольшом конце). На данный момент XSLT не так сложен, он просто удаляет некоторые узлы, которые соответствуют определенным критериям. У меня две проблемы:

  1. Это слишком медленно. Обработка 500 000 записей занимает 50 секунд, но этого недостаточно.
  2. Он потребляет 500 МБ памяти, так что это будет только хуже, когда файлы станут больше.

Есть ли что-нибудь, что я могу сделать в .net, чтобы заставить работать лучше?

Я знаю, что могу изучить синтаксический анализ на основе SAX или STX (который упоминается в другой публикации ), но я бы предпочел остаться в пределах границ .net

Спасибо!

EDIT: Вот мой XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="http://schemas....">
 <xsl:output omit-xml-declaration="yes"/>
    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
</xsl:template>
<xsl:template match="test:QueryRow[test:Columns/test:QueryColumn[test:Name='hit_count' and test:Value>200]]"/>
</xsl:stylesheet>

Вот код, который я использую для преобразования

XslCompiledTransform compiledTransform = new XslCompiledTransform();
XsltSettings settings = new XsltSettings();
settings.EnableScript = true;
XmlReader xmlReader = XmlReader.Create("in.xml");
XmlWriter xmlWriter = XmlWriter.Create("out.xml");
compiledTransform.Load("format.xslt", settings, null);
compiledTransform.Transform(xmlReader, xmlWriter); //this is what takes a long time

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

Ответы [ 3 ]

3 голосов
/ 07 января 2010

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

oXygen HotSpots

У вас могут быть неэффективные выражения XPATH (например, // *) или логика, скрытая в ваших шаблонах (например, множество for-each, if, select и т. Д.), Которая препятствует оптимизации движка XSLT. Перемещение некоторой этой логики в критерии соответствия шаблону может помочь движку оптимизировать и уменьшить размер наборов узлов, для которых вы выполняете итерацию и оценку.

2 голосов
/ 08 января 2010

Выражение XPath, по которому вы фильтруете, не имеет ничего заведомо неправильного. Но легко представить, что это проблема. Если все ваши элементы QueryRow имеют 20 Column дочерних элементов, каждый из которых имеет 20 QueryColumn дочерних элементов, процессору XSLT придется проверить 400 элементов, прежде чем решить, что данный элемент QueryRow не соответствует. Это, вероятно, довольно неэффективно, потому что если выясняется, что элемент не должен фильтроваться, процессор XSLT должен снова посетить все 400 элементов, чтобы вывести их все.

.NET способ реализовать SAX-подобный синтаксический анализ XML - это создать подкласс XmlReader, что вы могли бы предположительно сделать в этом случае: вы в основном создаете XmlReader, который буферизует элементы QueryRow, когда он читает их потомков до определяет, что они в порядке, а затем возвращает их вызывающему методу Read. Это будет значительно быстрее, чем использование XSLT для фильтрации XML, поскольку использование XmlReader не требует создания представления в памяти нефильтрованного XML-документа, прежде чем вы сможете его фильтровать.

1 голос
/ 07 января 2010

Вы можете попробовать Saxon , который, как я слышал, является очень хорошим и эффективным процессором XSLT. Но полный XSLT невозможно обработать потоковым способом, даже если ваше преобразование звучит так, как могло бы быть, поэтому, если процессор XSLT не очень хорош в оптимизации (как я понимаю, Saxon - один из лучших, если не лучший ), проблемы с потреблением памяти могут быть не решены.

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