Статьи

Как ускорить процессор XPath Apache Xalan в 10 раз

Некоторое время назад в Apache Xalan была некоторая неловкая ошибка, и это ошибка XALANJ-2540 . Результатом этой ошибки является то, что внутренний файл конфигурации SPI загружается Xalan тысячи раз за оценку выражения XPath, что можно легко измерить следующим образом:

это:

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
// 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);

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

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

Каждый раз! :

Сеанс профилирования на Xalan

Сеанс профилирования на Xalan

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

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

или же

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
// Code from c.s.o.a.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

Ресурсы

Приведенный выше текст является выдержкой из вопроса и ответа о переполнении стека, который я предоставил общественности некоторое время назад. Я снова публикую это здесь, в моем блоге, так что осведомленность сообщества об этой довольно серьезной ошибке может быть повышена. Не стесняйтесь высказаться по этому билету здесь, так как это влияет на каждый JDK Sun / Oracle на этой планете: https://issues.apache.org/jira/browse/XALANJ-2540

Внесение исправления в Apache было бы еще лучше, конечно …

Ссылка: Как ускорить процессор XPath Apache Xalan в 10 раз от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и JOOQ .