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

[email protected]
Newsgroups gmane.text.xml.xindice.devel
Message-ID <[email protected]>
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'>" +
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.