You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2010/08/16 16:05:57 UTC

svn commit: r985937 - in /jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance: AbstractPerformanceTest.java AbstractTest.java ConcurrentReadTest.java ConcurrentReadWriteTest.java

Author: jukka
Date: Mon Aug 16 14:05:57 2010
New Revision: 985937

URL: http://svn.apache.org/viewvc?rev=985937&view=rev
Log:
JCR-2699: Improve read/write concurrency

Use random background readers in the concurrency tests

Improved reporting from test cases

Modified:
    jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractPerformanceTest.java
    jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractTest.java
    jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadTest.java
    jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadWriteTest.java

Modified: jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractPerformanceTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractPerformanceTest.java?rev=985937&r1=985936&r2=985937&view=diff
==============================================================================
--- jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractPerformanceTest.java (original)
+++ jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractPerformanceTest.java Mon Aug 16 14:05:57 2010
@@ -26,6 +26,7 @@ import javax.jcr.SimpleCredentials;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.FileWriterWithEncoding;
 import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
 import org.apache.jackrabbit.core.RepositoryImpl;
 import org.apache.jackrabbit.core.config.RepositoryConfig;
@@ -66,54 +67,55 @@ public abstract class AbstractPerformanc
 
     private void testPerformance(String name, RepositoryImpl repository)
             throws Exception {
-        File report = new File("target", "performance-" + name + ".txt");
-        PrintWriter writer = new PrintWriter(report, "UTF-8");
+        PerformanceTestSuite suite = new PerformanceTestSuite(
+                repository,
+                new SimpleCredentials("admin", "admin".toCharArray()));
+        runTest(suite, new LoginTest(), name);
+        runTest(suite, new LoginLogoutTest(), name);
+        runTest(suite, new SmallFileReadTest(), name);
+        runTest(suite, new SmallFileWriteTest(), name);
+        runTest(suite, new BigFileReadTest(), name);
+        runTest(suite, new BigFileWriteTest(), name);
+        runTest(suite, new ConcurrentReadTest(), name);
+        runTest(suite, new ConcurrentReadWriteTest(), name);
+        runTest(suite, new SimpleSearchTest(), name);
+        runTest(suite, new CreateManyChildNodesTest(), name);
+        runTest(suite, new UpdateManyChildNodesTest(), name);
+        runTest(suite, new TransientManyChildNodesTest(), name);
+    }
+
+    private void runTest(
+            PerformanceTestSuite suite, AbstractTest test, String name)
+            throws Exception {
+        DescriptiveStatistics statistics = suite.runTest(test);
+
+        File base = new File("..", "base");
+        File target = new File(base, "target");
+        File report = new File(target, test + ".txt");
+        boolean needsPrefix = !report.exists();
+
+        PrintWriter writer = new PrintWriter(
+                new FileWriterWithEncoding(report, "UTF-8", true));
         try {
+            if (needsPrefix) {
+                writer.format(
+                        "# %-34.34s     avg     std     min     max   count%n",
+                        test);
+            }
+
             writer.format(
-                    "%-36.36s     avg     std     min     max   count%n",
-                    name);
-            writer.println(
-                    "--------------------------------------"
-                    + "--------------------------------------");
-
-            PerformanceTestSuite suite = new PerformanceTestSuite(
-                    repository,
-                    new SimpleCredentials("admin", "admin".toCharArray()));
-            runTest(suite, new LoginTest(), writer, name);
-            runTest(suite, new LoginLogoutTest(), writer, name);
-            runTest(suite, new SmallFileReadTest(), writer, name);
-            runTest(suite, new SmallFileWriteTest(), writer, name);
-            runTest(suite, new BigFileReadTest(), writer, name);
-            runTest(suite, new BigFileWriteTest(), writer, name);
-            runTest(suite, new ConcurrentReadTest(), writer, name);
-            runTest(suite, new ConcurrentReadWriteTest(), writer, name);
-            runTest(suite, new SimpleSearchTest(), writer, name);
-            runTest(suite, new CreateManyChildNodesTest(), writer, name);
-            runTest(suite, new UpdateManyChildNodesTest(), writer, name);
-            runTest(suite, new TransientManyChildNodesTest(), writer, name);
-
-            writer.println(
-                    "--------------------------------------"
-                    + "--------------------------------------");
+                    "%-36.36s  %6.0f  %6.0f  %6.0f  %6.0f  %6d%n",
+                    name,
+                    statistics.getMean(),
+                    statistics.getStandardDeviation(),
+                    statistics.getMin(),
+                    statistics.getMax(),
+                    statistics.getN());
         } finally {
             writer.close();
         }
     }
 
-    private void runTest(
-            PerformanceTestSuite suite, AbstractTest test,
-            PrintWriter writer, String name) throws Exception {
-        DescriptiveStatistics statistics = suite.runTest(test);
-        writer.format(
-                "%-36.36s  %6.0f  %6.0f  %6.0f  %6.0f  %6d%n",
-                name + " \""+ test + "\"",
-                statistics.getMean(),
-                statistics.getStandardDeviation(),
-                statistics.getMin(),
-                statistics.getMax(),
-                statistics.getN());
-    }
-
     /**
      * Creates a named test repository with the given configuration file.
      *

Modified: jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractTest.java?rev=985937&r1=985936&r2=985937&view=diff
==============================================================================
--- jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractTest.java (original)
+++ jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/AbstractTest.java Mon Aug 16 14:05:57 2010
@@ -80,13 +80,13 @@ public abstract class AbstractTest {
      * @throws Exception if the benchmark can not be cleaned up
      */
     public void tearDown() throws Exception {
-        afterSuite();
-
         this.running = false;
         for (Thread thread : threads) {
             thread.join();
         }
 
+        afterSuite();
+
         for (Session session : sessions) {
             if (session.isLive()) {
                 session.logout();

Modified: jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadTest.java?rev=985937&r1=985936&r2=985937&view=diff
==============================================================================
--- jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadTest.java (original)
+++ jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadTest.java Mon Aug 16 14:05:57 2010
@@ -16,25 +16,20 @@
  */
 package org.apache.jackrabbit.performance;
 
-import java.util.concurrent.CountDownLatch;
+import java.util.Random;
 
-import javax.jcr.ItemVisitor;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
-import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 /**
- * Test case that creates 10k unstructured nodes (100x100) and starts
- * 50 concurrent readers to traverse this content tree. Note that this
- * test measures total throughput of such a concurrent set of readers,
- * not the performance of individual readers nor the overall fairness of
- * the scheduling.
+ * Test case that traverses 10k unstructured nodes (100x100) while
+ * 50 concurrent readers randomly access nodes from within this tree.
  */
 public class ConcurrentReadTest extends AbstractTest {
 
-    private static final int NODE_COUNT = 100;
+    protected static final int NODE_COUNT = 100;
 
     private static final int READER_COUNT = 50;
 
@@ -42,15 +37,8 @@ public class ConcurrentReadTest extends 
 
     protected Node root;
 
-    private Thread[] readers = new Thread[READER_COUNT];
-
-    private volatile boolean running;
-
-    private volatile CountDownLatch latch;
-
     public void beforeSuite() throws Exception {
-        session = getRepository().login(getCredentials());
-
+        session = loginWriter();
         root = session.getRootNode().addNode("testroot", "nt:unstructured");
         for (int i = 0; i < NODE_COUNT; i++) {
             Node node = root.addNode("node" + i, "nt:unstructured");
@@ -60,59 +48,41 @@ public class ConcurrentReadTest extends 
             session.save();
         }
 
-        running = true;
-        latch = new CountDownLatch(0);
         for (int i = 0; i < READER_COUNT; i++) {
-            readers[i] = new Reader();
-            readers[i].start();
-            // Give the reader some time to get started
-            Thread.sleep(100); 
+            addBackgroundJob(new Reader());
         }
     }
 
-    private class Reader extends Thread implements ItemVisitor {
+    private class Reader implements Runnable {
+
+        private final Session session = loginReader();
+
+        private final Random random = new Random();
 
-        @Override
         public void run() {
             try {
-                Session session = getRepository().login();
-                try {
-                    Node node = session.getRootNode().getNode(root.getName());
-                    while (running) {
-                        node.accept(this);
-                        latch.countDown();
-                    }
-                } finally {
-                    session.logout();
-                }
+                int i = random.nextInt(NODE_COUNT);
+                int j = random.nextInt(NODE_COUNT);
+                session.getRootNode().getNode(
+                        "testroot/node" + i + "/node" + j);
             } catch (RepositoryException e) {
                 throw new RuntimeException(e);
             }
         }
 
-        public void visit(Node node) throws RepositoryException {
-            NodeIterator iterator = node.getNodes();
-            while (iterator.hasNext()) {
-                iterator.nextNode().accept(this);
-            }
-        }
-
-        public void visit(Property property) {
-        }
-
     }
 
     public void runTest() throws Exception {
-        latch = new CountDownLatch(READER_COUNT);
-        latch.await();
+        NodeIterator i = root.getNodes();
+        while (i.hasNext()) {
+            NodeIterator j = i.nextNode().getNodes();
+            while (j.hasNext()) {
+                j.nextNode();
+            }
+        }
     }
 
     public void afterSuite() throws Exception {
-        running = false;
-        for (int i = 0; i < READER_COUNT; i++) {
-            readers[i].join();
-        }
-
         for (int i = 0; i < NODE_COUNT; i++) {
             root.getNode("node" + i).remove();
             session.save();
@@ -120,7 +90,6 @@ public class ConcurrentReadTest extends 
 
         root.remove();
         session.save();
-        session.logout();
     }
 
 }

Modified: jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadWriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadWriteTest.java?rev=985937&r1=985936&r2=985937&view=diff
==============================================================================
--- jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadWriteTest.java (original)
+++ jackrabbit/trunk/test/performance/base/src/main/java/org/apache/jackrabbit/performance/ConcurrentReadWriteTest.java Mon Aug 16 14:05:57 2010
@@ -16,67 +16,45 @@
  */
 package org.apache.jackrabbit.performance;
 
-import javax.jcr.ItemVisitor;
+import java.util.Random;
+
 import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 
 /**
  * A {@link ConcurrentReadTest} with a single writer thread that continuously
- * updates the nodes being accessed by the concurrent readers.
+ * updates the nodes being accessed by the readers.
  */
 public class ConcurrentReadWriteTest extends ConcurrentReadTest {
 
-    private volatile boolean running;
-
-    private Thread writer;
-
     public void beforeSuite() throws Exception {
         super.beforeSuite();
 
-        running = true;
-        writer = new Writer();
-        writer.start();
+        addBackgroundJob(new Writer());
     }
 
-    private class Writer extends Thread implements ItemVisitor {
+    private class Writer implements Runnable {
+
+        private final Session session = loginReader();
+
+        private final Random random = new Random();
 
         private long count = 0;
 
-        @Override
         public void run() {
             try {
-                while (running) {
-                    root.accept(this);
-                }
+                int i = random.nextInt(NODE_COUNT);
+                int j = random.nextInt(NODE_COUNT);
+                Node node = session.getRootNode().getNode(
+                        "testroot/node" + i + "/node" + j);
+                node.setProperty("count", count++);
+                session.save();
             } catch (RepositoryException e) {
                 throw new RuntimeException(e);
             }
         }
 
-        public void visit(Node node) throws RepositoryException {
-            if (running) {
-                node.setProperty("count", count++);
-                node.getSession().save();
-
-                NodeIterator iterator = node.getNodes();
-                while (iterator.hasNext()) {
-                    iterator.nextNode().accept(this);
-                }
-            }
-        }
-
-        public void visit(Property property) {
-        }
-
-    }
-
-    public void afterSuite() throws Exception {
-        running = false;
-        writer.join();
-
-        super.afterSuite();
     }
 
 }