Производительность Java XPath (реализация Apache JAXP)




Примечание: Если вы испытываете эту проблему, а также, пожалуйста, upvote его на Apache JIRA:



https://issues.apache.org/jira/browse/XALANJ-2540




Я пришел к удивительному выводу, что это:



Element e = (Element) document.getElementsByTagName("SomeElementName").item(0);
String result = ((Element) e).getTextContent();


кажется невероятным 100x быстрее, чем это:



// Accounts for 30%, can be cached
XPathFactory factory = XPathFactory.newInstance();

// Negligible
XPath xpath = factory.newXPath();

// Negligible
XPathExpression expression = xpath.compile("//SomeElementName");

// Accounts for 70%
String result = (String) expression.evaluate(document, XPathConstants.STRING);


Я использую реализацию JVM по умолчанию JAXP:



org.apache.xpath.jaxp.XPathFactoryImpl
org.apache.xpath.jaxp.XPathImpl


Я совсем запутался, потому что легко видеть, как JAXP может оптимизировать вышеупомянутый запрос XPath, чтобы фактически выполнить простой . Но не похоже, чтобы сделать это. Эта проблема ограничена приблизительно 5-6 часто используемыми вызовами XPath, которые абстрагированы и скрыты API. Эти запросы включают в себя простые пути (например,/a/b/c, без переменных, условий) только для всегда доступного документа DOM. Таким образом, если оптимизация может быть выполнена, это будет довольно легко достичь.



мой вопрос: Является ли медлительность XPath признанный факт, или я что-то упускаю? Есть ли лучшая (более быстрая) реализация? Или я должен просто избегать XPath вообще, для простых запросов?

698   3  

3 ответов:

я отладил и профилировал мой тестовый случай и Xalan / JAXP в целом. Мне удалось определить большую главную проблему в

org.apache.xml.dtm.ObjectFactory.lookUpFactoryClassName()

видно, что каждая из 10k тестовых оценок XPath привела к тому, что загрузчик классов пытается найти DTMManager например, в какой-то конфигурации по умолчанию. Эта конфигурация не загружается в память, но доступна каждый раз. Кроме того, этот доступ, по-видимому, защищен блокировкой на ObjectFactory.class сам по себе. Когда не удается получить доступ (по по умолчанию), то конфигурация загружается из xalan.jar файла

META-INF/service/org.apache.xml.dtm.DTMManager

файл конфигурации. каждый раз!:

JProfiler profiling results

к счастью, это поведение можно переопределить, указав параметр JVM следующим образом:

-Dorg.apache.xml.dtm.DTMManager=
  org.apache.xml.dtm.ref.DTMManagerDefault

или

-Dcom.sun.org.apache.xml.internal.dtm.DTMManager=
  com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault

вышеописанные работы, так как это позволит обойти дорогостоящие работы в lookUpFactoryClassName() если имя Заводского класса по умолчанию так или иначе:

// Code from com.sun.org.apache.xml.internal.dtm.ObjectFactory
static String lookUpFactoryClassName(String factoryId,
                                     String propertiesFilename,
                                     String fallbackClassName) {
  SecuritySupport ss = SecuritySupport.getInstance();

  try {
    String systemProp = ss.getSystemProperty(factoryId);
    if (systemProp != null) { 

      // Return early from the method
      return systemProp;
    }
  } catch (SecurityException se) {
  }

  // [...] "Heavy" operations later

Итак, вот обзор повышения производительности для 10k последовательных оценок XPath //SomeNodeName против XML-файла 90k (измеряется с помощью System.nanoTime():

measured library        : Xalan 2.7.0 | Xalan 2.7.1 | Saxon-HE 9.3 | jaxen 1.1.3
--------------------------------------------------------------------------------
without optimisation    :     10400ms |      4717ms |              |     25500ms
reusing XPathFactory    :      5995ms |      2829ms |              |
reusing XPath           :      5900ms |      2890ms |              |
reusing XPathExpression :      5800ms |      2915ms |      16000ms |     25000ms
adding the JVM param    :      1163ms |       761ms |        n/a   |

обратите внимание, что тест был очень примитивный. вполне может быть, что ваш собственный бенчмарк покажет, что saxon превосходит xalan

я подал это как ошибку для парней Xalan в Apache:

https://issues.apache.org/jira/browse/XALANJ-2540

Не решение, а указатель на основную проблему: Элемент медленная частью процесса оценки xpath по отношению к произвольному узлу является время, которое требуется менеджеру DTM для поиска дескриптора узла:

http://javasourcecode.org/html/open-source/jdk/jdk-6u23/com/sun/org/apache/xml/internal/dtm/ref/dom2dtm/DOM2DTM.html#getHandleOfNode%28org.w3c.dom.Node%29

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

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

чтобы ответить на ваш вопрос, vtd-xml намного быстрее, чем Jaxen или Xalan) (я бы сказал, в среднем 10x, и 60x было сообщено...

Comments

    Ничего не найдено.