Skip to content

Xpath matcher poor performance #1048

@philippe-granet

Description

@philippe-granet

Wiremock version: 2.19.0

First of all, thank you for your work on wiremock, a very useful tool!

We are using wiremock for stubbing SOAP services in development environment.
We also tried to use Wiremock for performance tests, but there is some bottleneck:

Simply set system property -Djavax.xml.transform.TransformerFactory=<implementation to load> resolve this bottleneck

Simply set system property -Djavax.xml.xpath.XPathFactory:http://java.sun.com/jaxp/xpath/dom=<implementation to load> resolve this bottleneck

  • XMLUnit.setXPathFactory and XMLUnit.setTransformerFactory
    Predefine theses factories in XMLUnit also improve performance

Simple test case:

@Test
public void perfXmlTest() {
	perfRunDatas("without optimisations");

	// Optimisation 1
	String xPathFactoryImpl = XPathFactory.newInstance().getClass().getName();
	System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + ":" 
		+ XPathFactory.DEFAULT_OBJECT_MODEL_URI, xPathFactoryImpl);
	perfRunDatas("with XPathFactory system property");

	// Optimisation 2
	String transformerFactoryImpl = TransformerFactory.newInstance().getClass().getName();
	System.setProperty(TransformerFactory.class.getName(), transformerFactoryImpl);
	perfRunDatas("with XPathFactory/TransformerFactory system properties");

	// Optimisation 3
	XMLUnit.setTransformerFactory(transformerFactoryImpl);
	perfRunDatas("with XPathFactory/TransformerFactory system properties and TransformerFactory predefined in XMLUnit");

	// Optimisation 4
	XMLUnit.setXPathFactory(xPathFactoryImpl);
	perfRunDatas("with XPathFactory/TransformerFactory system properties and TransformerFactory/XPathFactory predefined in XMLUnit");
}
private void perfRunDatas(String string) {
	long ts = System.currentTimeMillis();
	for (int i = 0; i < 10000; i++) {
		WireMock.matchingXPath("//perf-test").match("<perf-test>perf-data</perf-test>");
	}
	System.out.println(string + ":\n" + (System.currentTimeMillis() - ts) + "ms");
}

generate this:
without optimisations:
23745ms
with XPathFactory system property:
12690ms
with XPathFactory/TransformerFactory system properties:
2032ms
with XPathFactory/TransformerFactory system properties and TransformerFactory predefined in XMLUnit:
1981ms
with XPathFactory/TransformerFactory system properties and TransformerFactory/XPathFactory predefined in XMLUnit:
1767ms

So, simply adding to system properties:
-Djavax.xml.transform.TransformerFactory=<implementation>
-Djavax.xml.xpath.XPathFactory:http://java.sun.com/jaxp/xpath/dom=<implementation>
and predefining factories in XMLUnit library improved performance by 10 !

I think this should be described in documentation, or implemented in Wiremock.
An implementation could be calling this method optimizeFactoriesLoading() during WireMock initialisation :

public void optimizeFactoriesLoading() {
	
	String transformerFactoryImpl = TransformerFactory.newInstance().getClass().getName();
	String xPathFactoryImpl = XPathFactory.newInstance().getClass().getName();
	
	setProperty(TransformerFactory.class.getName(), transformerFactoryImpl);
	setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + ":" + XPathFactory.DEFAULT_OBJECT_MODEL_URI,
		xPathFactoryImpl);

	XMLUnit.setTransformerFactory(transformerFactoryImpl);
	XMLUnit.setXPathFactory(xPathFactoryImpl);
}
private String setProperty(final String name, final String value) {
	return AccessController.doPrivileged(new PrivilegedAction<String>() {
		@Override
		public String run() {
			return System.setProperty(name, value);
		}
	});
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions