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'>" +