You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xindice-dev@xml.apache.org by vg...@apache.org on 2008/11/09 22:55:21 UTC
svn commit: r712568 - in /xml/xindice/trunk/java:
src/org/apache/xindice/core/query/XPathQueryResolver.java
src/org/apache/xindice/core/xupdate/XPathQueryImpl.java
tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java
Author: vgritsenko
Date: Sun Nov 9 13:55:21 2008
New Revision: 712568
URL: http://svn.apache.org/viewvc?rev=712568&view=rev
Log:
optimize xpath query performance.
tweak indexed search test - does not run reliably in xmlrpc integration tests mode
due to network overhead.
Modified:
xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java
xml/xindice/trunk/java/src/org/apache/xindice/core/xupdate/XPathQueryImpl.java
xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java
Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java?rev=712568&r1=712567&r2=712568&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/query/XPathQueryResolver.java Sun Nov 9 13:55:21 2008
@@ -102,8 +102,6 @@
private static final Log log = LogFactory.getLog(XPathQueryResolver.class);
- private static final Key[] EMPTY_KEYS = new Key[0];
- private static final Key[][] EMPTY_KEYSET = new Key[0][0];
private static final String WILDCARD = "*";
public static final String STYLE_XPATH = "XPath";
@@ -335,7 +333,7 @@
while (rs.hasMoreRecords()) {
set.add(rs.getNextKey());
}
- keySet = (Key[]) set.toArray(EMPTY_KEYS);
+ keySet = (Key[]) set.toArray(new Key[set.size()]);
}
return new ResultSet(context, pr, keySet, query, parameters);
@@ -348,15 +346,16 @@
}
private Key[] andKeys(List list) {
- if (!list.isEmpty()) {
- if (list.size() > 1) {
- Key[][] keys = (Key[][]) list.toArray(EMPTY_KEYSET);
- return QueryEngine.andKeySets(keys);
- } else
- return (Key[]) list.get(0);
- } else {
+ if (list.isEmpty()) {
return null;
}
+
+ if (list.size() > 1) {
+ Key[][] keys = (Key[][]) list.toArray(new Key[list.size()][]);
+ return QueryEngine.andKeySets(keys);
+ }
+
+ return (Key[]) list.get(0);
}
// Evaluation Methods
@@ -1121,7 +1120,9 @@
Indexer idx = context.getIndexManager().getBestIndexer(Indexer.STYLE_NODEVALUE, pattern);
if (idx != null) {
return new NamedKeys(nk.name, nk.attribute, QueryEngine.getUniqueKeys(idx.queryMatches(iq)));
- } else if (autoIndex) {
+ }
+
+ if (autoIndex) {
// TODO: This has to *not* be hardcoded
Element e = new DocumentImpl().createElement("index");
e.setAttribute("class", "org.apache.xindice.core.indexer.ValueIndexer");
@@ -1284,9 +1285,8 @@
/**
* NamedKeys
*/
-
- private class NamedKeys {
- public boolean attribute = false;
+ private static class NamedKeys {
+ public boolean attribute;
public NodePath name;
public Key[] keys;
@@ -1297,21 +1297,40 @@
}
}
+ private static final ErrorListener XPATH_ERROR_LISTENER = new ErrorListener() {
+ public void fatalError(TransformerException te) {
+ if (log.isFatalEnabled()) {
+ log.fatal("No message", te);
+ }
+ }
+
+ public void error(TransformerException te) {
+ if (log.isErrorEnabled()) {
+ log.error("No message", te);
+ }
+ }
+
+ public void warning(TransformerException te) {
+ if (log.isWarnEnabled()) {
+ log.warn("No message", te);
+ }
+ }
+ };
+
/**
* ResultSet
*/
-
private class ResultSet implements NodeSet {
- public Collection context;
- public String query;
- public ErrorListener errors;
- public PrefixResolver pr;
- public XPath xp;
-
- public Key[] keySet;
- public int keyPos = 0;
- public NodeIterator ni;
- public Object node;
+ private Collection context;
+ private String query;
+ private PrefixResolver pr;
+ private XPathResolverContext xpc;
+ private XPath xp;
+
+ private Key[] keySet;
+ private int keyPos = 0;
+ private NodeIterator ni;
+ private Object node;
private Map parameters;
public ResultSet(Collection context, PrefixResolver pr, Key[] keySet, String query, Map parameters) {
@@ -1321,26 +1340,6 @@
this.query = query;
this.parameters = parameters;
- errors = new ErrorListener() {
- public void fatalError(TransformerException te) {
- if (log.isFatalEnabled()) {
- log.fatal("No message", te);
- }
- }
-
- public void error(TransformerException te) {
- if (log.isErrorEnabled()) {
- log.error("No message", te);
- }
- }
-
- public void warning(TransformerException te) {
- if (log.isWarnEnabled()) {
- log.warn("No message", te);
- }
- }
- };
-
try {
prepareNextNode();
} catch (Exception e) {
@@ -1352,10 +1351,10 @@
try {
if (XCOMPILER3) {
return (XPath) XPATH.newInstance(
- new Object[] {query, null, pfx, new Integer(XPath.SELECT), errors, functionTable});
+ new Object[] {query, null, pfx, new Integer(XPath.SELECT), XPATH_ERROR_LISTENER, functionTable});
} else {
return (XPath) XPATH.newInstance(
- new Object[] {query, null, pfx, new Integer(XPath.SELECT), errors});
+ new Object[] {query, null, pfx, new Integer(XPath.SELECT), XPATH_ERROR_LISTENER});
}
} catch (Exception e) {
throw new RuntimeException("Could not instantiate Compiler: " + e);
@@ -1383,7 +1382,10 @@
continue;
}
- XPathResolverContext xpc = new XPathResolverContext(parameters);
+ if (xpc == null) {
+ xpc = new XPathResolverContext(parameters);
+ }
+
PrefixResolver pfx;
if (pr == null) {
pfx = new PrefixResolverDefault(d.getDocumentElement());
@@ -1463,52 +1465,30 @@
/* This only implements what we need internally */
private static class EmptyNodeIterator implements NodeIterator {
-
- /* (non-Javadoc)
- * @see org.w3c.dom.traversal.NodeIterator#getWhatToShow()
- */
public int getWhatToShow() {
throw new UnsupportedOperationException();
}
- /* (non-Javadoc)
- * @see org.w3c.dom.traversal.NodeIterator#detach()
- */
public void detach() {
throw new UnsupportedOperationException();
}
- /* (non-Javadoc)
- * @see org.w3c.dom.traversal.NodeIterator#getExpandEntityReferences()
- */
public boolean getExpandEntityReferences() {
throw new UnsupportedOperationException();
}
- /* (non-Javadoc)
- * @see org.w3c.dom.traversal.NodeIterator#getRoot()
- */
public Node getRoot() {
throw new UnsupportedOperationException();
}
- /* (non-Javadoc)
- * @see org.w3c.dom.traversal.NodeIterator#nextNode()
- */
public Node nextNode() throws DOMException {
return null;
}
- /* (non-Javadoc)
- * @see org.w3c.dom.traversal.NodeIterator#previousNode()
- */
public Node previousNode() throws DOMException {
throw new UnsupportedOperationException();
}
- /* (non-Javadoc)
- * @see org.w3c.dom.traversal.NodeIterator#getFilter()
- */
public NodeFilter getFilter() {
throw new UnsupportedOperationException();
}
@@ -1538,8 +1518,8 @@
/**
* Helper class to track path to a node in the XPath expression
*/
- private class NodePath {
- private boolean absolute = false;
+ private static class NodePath {
+ private boolean absolute;
private LinkedList path = new LinkedList();
private String attr;
Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/xupdate/XPathQueryImpl.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/xupdate/XPathQueryImpl.java?rev=712568&r1=712567&r2=712568&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/xupdate/XPathQueryImpl.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/xupdate/XPathQueryImpl.java Sun Nov 9 13:55:21 2008
@@ -37,9 +37,8 @@
*/
public final class XPathQueryImpl implements XPathQuery {
private String qstring;
- private Node rootNode;
private Node namespace;
- private NodeFilter filter;
+ private XPathContext xpc;
private XPath xpath;
/**
@@ -50,6 +49,7 @@
*/
public void setQString(String qstring) throws Exception {
this.qstring = qstring;
+ this.xpath = null;
}
/**
@@ -60,6 +60,7 @@
*/
public void setNamespace(Node namespace) throws Exception {
this.namespace = namespace;
+ this.xpath = null;
}
/**
@@ -69,7 +70,7 @@
* @exception Exception Description of Exception
*/
public void setNodeFilter(NodeFilter filter) throws Exception {
- this.filter = filter;
+ // this.filter = filter;
}
/**
@@ -84,28 +85,31 @@
rootNode = ((Document) rootNode).getDocumentElement();
}
- this.rootNode = rootNode;
-
// Since we don't have a XML Parser involved here, install some default
// support for things like namespaces, etc.
- XPathContext xpathSupport = new XPathContext();
+ if (xpc == null) {
+ xpc = new XPathContext();
+ }
- PrefixResolver prefixResolver = null;
// Create an object to resolve namespace prefixes.
+ PrefixResolver pfx;
if (namespace != null) {
if (namespace.getNodeType() == Node.DOCUMENT_NODE) {
namespace = ((Document) namespace).getDocumentElement();
}
- prefixResolver = new PrefixResolverDefault(namespace);
+ pfx = new PrefixResolverDefault(namespace);
} else {
- prefixResolver = new PrefixResolverDefault(rootNode);
+ pfx = new PrefixResolverDefault(rootNode);
+ xpath = null;
}
// Create the XPath object.
- xpath = new XPath(qstring, null, prefixResolver, XPath.SELECT, null);
+ if (xpath == null) {
+ xpath = new XPath(qstring, null, pfx, XPath.SELECT, null);
+ }
// execute the XPath query on the specified root node
- return new XObjectImpl(xpath.execute(xpathSupport, rootNode, prefixResolver));
+ return new XObjectImpl(xpath.execute(xpc, rootNode, pfx));
}
}
Modified: xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java?rev=712568&r1=712567&r2=712568&view=diff
==============================================================================
--- xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java (original)
+++ xml/xindice/trunk/java/tests/src/org/apache/xindice/integration/client/services/IndexedSearchTest.java Sun Nov 9 13:55:21 2008
@@ -19,8 +19,6 @@
package org.apache.xindice.integration.client.services;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.apache.xindice.integration.client.AbstractXmlDbClientTest;
import org.apache.xindice.integration.client.XmlDbClientSetup;
import org.apache.xindice.xml.NodeSource;
@@ -51,8 +49,6 @@
*/
public class IndexedSearchTest extends AbstractXmlDbClientTest {
- private static final Log itsLog = LogFactory.getLog(IndexedSearchTest.class);
-
/**
* path of collection we use (and reuse to avoid document insertion overhead for each test case)
*/
@@ -119,7 +115,7 @@
public Result(ResourceSet theResourceSet,
long theElapsedTime) {
itsResourceSet = theResourceSet;
- itsElapsedTime = theElapsedTime;
+ itsElapsedTime = theElapsedTime > 0 ? theElapsedTime : 1;
}
/**
@@ -150,8 +146,8 @@
private long itsExpectedResourceCount;
private Object[] itsExpectedResources;
private int itsIndexSpeedupFactor;
- private boolean itsIndexCreated = false;
- private boolean itsTestDocumentsAdded = false;
+ private boolean itsIndexCreated;
+ private boolean itsTestDocumentsAdded;
/**
* Creates a new test definition.
@@ -197,14 +193,15 @@
Result aResult = runNonIndexed();
checkResult(aResult);
long aNonIndexedTime = aResult.getElapsedTime();
+
aResult = runIndexed();
checkResult(aResult);
long anIndexedTime = aResult.getElapsedTime();
- itsLog.info(itsDescription +
- ": Non-indexed time = " + aNonIndexedTime +
- " Indexed time = " + anIndexedTime +
- " Index speedup:" + (anIndexedTime > 0 ? " " + aNonIndexedTime / anIndexedTime + "X" :
- anIndexedTime == 0 ? " >" + aNonIndexedTime + "X" : " (Indexed query not run)"));
+
+ long speedUp = aNonIndexedTime / anIndexedTime;
+ System.out.println(itsDescription + ": Non-indexed: " + aNonIndexedTime + "ms, " +
+ "Indexed: " + anIndexedTime + "ms, " +
+ "Speedup: " + speedUp + "x");
if (anIndexedTime * itsIndexSpeedupFactor > aNonIndexedTime) {
fail("Query apparently did not use index" +
" Non-indexed time = " + aNonIndexedTime + " Indexed time = " + anIndexedTime);
@@ -245,11 +242,17 @@
*/
public Result runQuery() throws Exception {
Collection col = IndexedSearchTest.this.client.getCollection(IndexedSearchTest.COLLECTION_PATH);
- XPathQueryService xpathservice = (XPathQueryService) col.getService("XPathQueryService", "1.0");
+ XPathQueryService service = (XPathQueryService) col.getService("XPathQueryService", "1.0");
+
+ // Warm Up
+ service.query(itsTestQuery);
- org.apache.xindice.Stopwatch aStopwatch = new org.apache.xindice.Stopwatch("Non-indexed starts-with query", true);
- ResourceSet resultSet = xpathservice.query(itsTestQuery);
+ org.apache.xindice.Stopwatch aStopwatch = new org.apache.xindice.Stopwatch(null, true);
+ // Run twice since indexed query takes too little time
+ service.query(itsTestQuery);
+ ResourceSet resultSet = service.query(itsTestQuery);
aStopwatch.stop();
+
return new Result(resultSet, aStopwatch.elapsed());
}
@@ -274,15 +277,8 @@
Node aNode = aResource.getContentAsDOM();
int anExpectedSourceDocumentIndex = ((Integer) itsExpectedResources[anIndex * 2]).intValue();
String anExpected = "<?xml version=\"1.0\"?>\n" + addSource((String) itsExpectedResources[anIndex * 2 + 1],
- TEST_DOCUMENT_PREFIX + anExpectedSourceDocumentIndex,
- IndexedSearchTest.COLLECTION_PATH);
+ TEST_DOCUMENT_PREFIX + anExpectedSourceDocumentIndex);
String anActual = TextWriter.toString(aNode);
- //itsLog.info(itsDescription);
- //itsLog.info("Expected resource " + (anIndex / 2) + ":");
- //itsLog.info("Expected:");
- //itsLog.info(anExpected);
- //itsLog.info("Actual:");
- //itsLog.info(anActual);
XMLAssert.assertXMLEqual("While checking target Resource " + anIndex,
anExpected, anActual);
}
@@ -295,9 +291,8 @@
*
* @param theXML XML to add source to
* @param theKey document key to add
- * @param theCollectionName source collection to add
*/
- public String addSource(String theXML, String theKey, String theCollectionName) throws Exception {
+ public String addSource(String theXML, String theKey) throws Exception {
DocumentBuilder aBuilder = itsDocumentBuilderFactory.newDocumentBuilder();
Document aDocument = aBuilder.parse(
new InputSource(new StringReader(theXML)));
@@ -305,8 +300,7 @@
final String pfx = "src";
elm.setAttribute(NodeImpl.XMLNS_PREFIX + ":" + pfx, NodeSource.SOURCE_NS);
- elm.setAttribute(pfx + ":" + NodeSource.SOURCE_COL,
- "/" + COLLECTION_PATH);
+ elm.setAttribute(pfx + ":" + NodeSource.SOURCE_COL, "/" + COLLECTION_PATH);
elm.setAttribute(pfx + ":" + NodeSource.SOURCE_KEY, theKey);
return TextWriter.toString(elm);
}
@@ -389,7 +383,7 @@
"SENA", // index name
"Name", // index type
"address", // index pattern
- 8, // indexed query speedup expected (conservative)
+ 5, // indexed query speedup expected (conservative)
new String[] { // test docs specifically for this test
"<?xml version='1.0'?>" +
"<person number3='yes'>" +
@@ -446,7 +440,7 @@
"SENA", // index name
"Name", // index type
"second", // index pattern
- 10, // indexed query speedup expected (conservative)
+ 6, // indexed query speedup expected (conservative)
new String[] { // test docs specifically for this test
"<?xml version='1.0'?>" +
"<person number3='yes'>" +
@@ -483,7 +477,7 @@
"SESA", // index name
"Name", // index type
"phone@call", // index pattern
- 8, // indexed query speedup expected (conservative)
+ 9, // indexed query speedup expected (conservative)
new String[] { // test docs specifically for this test
"<?xml version='1.0'?>" +
"<person number3='yes'>" +
@@ -519,7 +513,7 @@
"SEWA", // index name
"Name", // index type
"second@*", // index pattern
- 6, // indexed query speedup expected (conservative)
+ 7, // indexed query speedup expected (conservative)
new String[] { // test docs specifically for this test
"<?xml version='1.0'?>" +
"<person number3='yes'>" +
@@ -666,7 +660,7 @@
"SENA", // index name
"Value", // index type
"last", // index pattern
- 8, // indexed query speedup expected (conservative)
+ 6, // indexed query speedup expected (conservative)
new String[] { // test docs specifically for this test
"<?xml version='1.0'?>" +
"<person number3='yes'>" +
@@ -768,7 +762,7 @@
"SESA", // index name
"Value", // index type
"phone@call", // index pattern
- 6, // indexed query speedup expected (conservative)
+ 9, // indexed query speedup expected (conservative)
new String[] { // test docs specifically for this test
"<?xml version='1.0'?>" +
"<person number3='yes'>" +
@@ -802,7 +796,7 @@
"SENA", // index name
"Value", // index type
"*@call", // index pattern
- 6, // indexed query speedup expected (conservative)
+ 9, // indexed query speedup expected (conservative)
new String[] { // test docs specifically for this test
"<?xml version='1.0'?>" +
"<person number3='yes'>" +
@@ -948,7 +942,7 @@
"SESA", // index name
"Value", // index type
"/person/phone@call", // index pattern
- 6, // indexed query speedup expected (conservative)
+ 9, // indexed query speedup expected (conservative)
new String[] { // test docs specifically for this test
"<?xml version='1.0'?>" +
"<person number3='yes'>" +