Я отладил и профилировал мой тестовый пример и Xalan / JAXP в целом. Мне удалось определить большую серьезную проблему в
org.apache.xml.dtm.ObjectFactory.lookUpFactoryClassName()
Видно, что каждый из тестов XPath с тестом 10k приводил к тому, что загрузчик классов пытался найти экземпляр DTMManager
в какой-то конфигурации по умолчанию. Эта конфигурация не загружается в память, а доступна каждый раз. Кроме того, этот доступ, кажется, защищен блокировкой самого ObjectFactory.class
. При сбое доступа (по умолчанию) конфигурация загружается из xalan.jar
файла
META-INF/service/org.apache.xml.dtm.DTMManager
файл конфигурации. Каждый раз! :
К счастью, это поведение можно изменить, указав параметр 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 |
обратите внимание, что тест был очень примитивным. вполне возможно, что ваш собственный тест покажет, что саксон превосходит xalan
Я подал это как ошибку для парней из Халана в Apache:
https://issues.apache.org/jira/browse/XALANJ-2540