Java XPath (Apache JAXP 구현) 성능
참고 :이 문제도 경험하는 경우 Apache JIRA에서 upvote하십시오 :
나는 다음과 같은 놀라운 결론에 도달했습니다.
Element e = (Element) document.getElementsByTagName("SomeElementName").item(0);
String result = ((Element) e).getTextContent();
이것보다 100 배 더 빠른 것 같습니다 :
// 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 쿼리를 어떻게 최적화하여 실제로 간단한 getElementsByTagName()
대신 실행할 수 있는지 쉽게 알 수 있기 때문에 정말 혼란 스럽습니다 . 그러나 그것은 그렇게하지 않는 것 같습니다. 이 문제는 API에 의해 추상화되고 숨겨진 약 5 ~ 6 개의 자주 사용되는 XPath 호출로 제한됩니다. 이러한 쿼리에는 /a/b/c
항상 사용 가능한 DOM 문서에 대한 간단한 경로 (예 : 변수 없음, 조건)가 포함됩니다. 따라서 최적화를 수행 할 수 있다면 달성하기가 매우 쉽습니다.
내 질문 : XPath의 느린 속도가 허용되는 사실입니까, 아니면 무언가를 간과하고 있습니까? 더 나은 (빠른) 구현이 있습니까? 아니면 단순한 쿼리를 위해 XPath를 아예 피해야합니까?
일반적으로 테스트 케이스와 Xalan / JAXP를 디버깅하고 프로파일 링했습니다. 나는 큰 문제를 파악할 수 있었다.
org.apache.xml.dtm.ObjectFactory.lookUpFactoryClassName()
10k 테스트 XPath 평가의 모든 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
따라서 다음 //SomeNodeName
은 90k XML 파일에 대한 10k 연속 XPath 평가에 대한 성능 개선 개요입니다 (다음으로 측정) 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을 능가한다는 것을 보여줄 수 있습니다.
나는 이것을 Apache의 Xalan 사람들에게 버그로 제출했습니다.
https://issues.apache.org/jira/browse/XALANJ-2540
해결책은 아니지만 주요 문제에 대한 포인터 : 임의의 노드와 관련하여 xpath를 평가하는 프로세스에서 가장 느린 부분은 DTM 관리자가 노드 핸들을 찾는 데 걸리는 시간입니다.
문제의 노드가 문서의 끝에 있으면 각 쿼리에 대해 전체 트리를 걸어 문제의 노드를 찾을 수 있습니다.
이것은 대상 노드를 분리하는 해킹이 작동하는 이유를 설명합니다. 이러한 조회를 캐시하는 방법 이 있어야 하지만이 시점에서 방법을 볼 수 없습니다.
귀하의 질문에 답하기 위해 vtd-xml은 Jaxen 또는 Xalan보다 훨씬 빠릅니다) (평균 10x라고 말하고 60x 가보고되었습니다 ...
참조 URL : https://stackoverflow.com/questions/6340802/java-xpath-apache-jaxp-implementation-performance
'programing' 카테고리의 다른 글
Eclipse에서 git의 두 개정판을 어떻게 비교할 수 있습니까? (0) | 2021.01.15 |
---|---|
Git은 100,000 개의 개체에 대해 정말 느립니다. (0) | 2021.01.15 |
diff의 오류 종료 값은 무엇입니까? (0) | 2021.01.15 |
similar_text는 어떻게 작동합니까? (0) | 2021.01.15 |
pdb.set_trace ()로 인해 nosetest가 중지되고 디버거로 떨어지지 않습니다. (0) | 2021.01.14 |