Index: plot.sh
===================================================================
--- plot.sh (revision 0)
+++ plot.sh (revision 0)
@@ -0,0 +1,61 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This is an example Gnuplot script for plotting the performance results
+# produced by the Jackrabbit performance test suite. Before you run this
+# script you need to preprocess the individual performance reports.
+
+cat <target/report.html
+
+
+ Jackrabbit performance
+
+
+
Jackrabbit performance
+
+HTML
+
+for dat in */target/*.txt; do
+ cat "$dat" >>target/`basename "$dat"`
+done
+
+for dat in target/*.txt; do
+ name=`basename "$dat" .txt`
+ rows=`grep -v "#" "$dat" | wc -l`
+ gnuplot <>target/report.html
+
+HTML
+done
+
+cat <>target/report.html
+
+
+
+HTML
+
+echo file://`pwd`/target/report.html
+
Property changes on: plot.sh
___________________________________________________________________
Added: svn:executable
+ *
Index: parent/pom.xml
===================================================================
--- parent/pom.xml (revision 0)
+++ parent/pom.xml (revision 0)
@@ -0,0 +1,111 @@
+
+
+
+
+
+ 4.0.0
+
+
+
+
+
+
+ org.apache
+ apache
+ 10
+
+
+
+ org.apache.jackrabbit.oak
+ oak-perf-parent
+ Oak Performance Test Parent
+ 0.3-SNAPSHOT
+ pom
+
+
+ \d\.\d
+ .*
+ 0
+
+
+
+
+
+
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+
+
+
+ maven-surefire-plugin
+
+ -Xms256m -Xmx512m
+ false
+
+
+ derby.stream.error.file
+ target/derby.log
+
+
+ repo
+ ${repo}
+
+
+ only
+ ${only}
+
+
+ scale
+ ${scale}
+
+
+
+
+
+
+
+
+
+
+ profiler
+
+
+ agentlib
+
+
+
+
+
+
+ maven-surefire-plugin
+
+ -Xmx512m -XX:MaxPermSize=512m -agentlib:${agentlib}
+
+
+
+
+
+
+
+
+
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/SQL2DescendantSearchTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/SQL2DescendantSearchTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/SQL2DescendantSearchTest.java (revision 0)
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+
+/**
+ * SQL-2 version of the sub-tree performance test.
+ */
+public class SQL2DescendantSearchTest extends DescendantSearchTest {
+
+ protected Query createQuery(QueryManager manager, int i)
+ throws RepositoryException {
+ return manager.createQuery(
+ "SELECT * FROM [nt:base] AS n WHERE ISDESCENDANTNODE(n, '/testroot') AND testcount=" + i,
+ "JCR-SQL2");
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/SetPropertyTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/SetPropertyTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/SetPropertyTest.java (revision 0)
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * Test for measuring the performance of setting a single property and
+ * saving the change.
+ */
+public class SetPropertyTest extends AbstractTest {
+
+ private Session session;
+
+ private Node node;
+
+ public void beforeSuite() throws RepositoryException {
+ session = getRepository().login(getCredentials());
+ node = session.getRootNode().addNode("testnode", "nt:unstructured");
+ session.save();
+ }
+
+ public void beforeTest() throws RepositoryException {
+ node.setProperty("count", -1);
+ session.save();
+ }
+
+ public void runTest() throws Exception {
+ for (int i = 0; i < 1000; i++) {
+ node.setProperty("count", i);
+ session.save();
+ }
+ }
+
+ public void afterTest() throws RepositoryException {
+ }
+
+ public void afterSuite() throws RepositoryException {
+ session.getRootNode().getNode("testnode").remove();
+ session.save();
+ session.logout();
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/LoginLogoutTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/LoginLogoutTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/LoginLogoutTest.java (revision 0)
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+public class LoginLogoutTest extends AbstractTest {
+
+ @Override
+ public void setUp(Repository repository, Credentials credentials)
+ throws Exception {
+ super.setUp(repository,
+ new SimpleCredentials("admin", "admin".toCharArray()));
+ }
+
+ public void runTest() throws RepositoryException {
+ Repository repository = getRepository();
+ for (int i = 0; i < 1000; i++) {
+ Session session = repository.login(getCredentials());
+ try {
+ session.getRootNode();
+ } finally {
+ session.logout();
+ }
+ }
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/AbstractTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/AbstractTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/AbstractTest.java (revision 0)
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * Abstract base class for individual performance benchmarks.
+ */
+public abstract class AbstractTest {
+
+ private Repository repository;
+
+ private Credentials credentials;
+
+ private List sessions;
+
+ private List threads;
+
+ private volatile boolean running;
+
+ protected static int getScale(int def) {
+ int scale = Integer.getInteger("scale", 0);
+ if (scale == 0) {
+ scale = def;
+ }
+ return scale;
+ }
+
+ /**
+ * Prepares this performance benchmark.
+ *
+ * @param repository the repository to use
+ * @param credentials credentials of a user with write access
+ * @throws Exception if the benchmark can not be prepared
+ */
+ public void setUp(Repository repository, Credentials credentials)
+ throws Exception {
+ this.repository = repository;
+ this.credentials = credentials;
+ this.sessions = new LinkedList();
+ this.threads = new LinkedList();
+
+ this.running = true;
+
+ beforeSuite();
+ }
+
+ /**
+ * Executes a single iteration of this test.
+ *
+ * @return number of milliseconds spent in this iteration
+ * @throws Exception if an error occurs
+ */
+ public long execute() throws Exception {
+ beforeTest();
+ try {
+ long start = System.currentTimeMillis();
+ runTest();
+ return System.currentTimeMillis() - start;
+ } finally {
+ afterTest();
+ }
+ }
+ /**
+ * Cleans up after this performance benchmark.
+ *
+ * @throws Exception if the benchmark can not be cleaned up
+ */
+ public void tearDown() throws Exception {
+ this.running = false;
+ for (Thread thread : threads) {
+ thread.join();
+ }
+
+ afterSuite();
+
+ for (Session session : sessions) {
+ if (session.isLive()) {
+ session.logout();
+ }
+ }
+
+ this.threads = null;
+ this.sessions = null;
+ this.credentials = null;
+ this.repository = null;
+ }
+
+ /**
+ * Run before any iterations of this test get executed. Subclasses can
+ * override this method to set up static test content.
+ *
+ * @throws Exception if an error occurs
+ */
+ protected void beforeSuite() throws Exception {
+ }
+
+ protected void beforeTest() throws Exception {
+ }
+
+ protected abstract void runTest() throws Exception;
+
+ protected void afterTest() throws Exception {
+ }
+
+ /**
+ * Run after all iterations of this test have been executed. Subclasses can
+ * override this method to clean up static test content.
+ *
+ * @throws Exception if an error occurs
+ */
+ protected void afterSuite() throws Exception {
+ }
+
+ protected void failOnRepositoryVersions(String... versions)
+ throws RepositoryException {
+ String repositoryVersion =
+ repository.getDescriptor(Repository.REP_VERSION_DESC);
+ for (String version : versions) {
+ if (repositoryVersion.startsWith(version)) {
+ throw new RepositoryException(
+ "Unable to run " + getClass().getName()
+ + " on repository version " + version);
+ }
+ }
+ }
+
+ protected Repository getRepository() {
+ return repository;
+ }
+
+ protected Credentials getCredentials() {
+ return credentials;
+ }
+
+ /**
+ * Returns a new reader session that will be automatically closed once
+ * all the iterations of this test have been executed.
+ *
+ * @return reader session
+ */
+ protected Session loginReader() {
+ try {
+ Session session = repository.login();
+ sessions.add(session);
+ return session;
+ } catch (RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Returns a new writer session that will be automatically closed once
+ * all the iterations of this test have been executed.
+ *
+ * @return writer session
+ */
+ protected Session loginWriter() {
+ try {
+ Session session = repository.login(credentials);
+ sessions.add(session);
+ return session;
+ } catch (RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Adds a background thread that repeatedly executes the given job
+ * until all the iterations of this test have been executed.
+ *
+ * @param job background job
+ */
+ protected void addBackgroundJob(final Runnable job) {
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ while (running) {
+ job.run();
+ }
+ }
+ };
+ thread.start();
+ threads.add(thread);
+ }
+
+ public String toString() {
+ String name = getClass().getName();
+ return name.substring(name.lastIndexOf('.') + 1);
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/UpdateManyChildNodesTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/UpdateManyChildNodesTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/UpdateManyChildNodesTest.java (revision 0)
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * Test for measuring the performance of adding one extra child node to
+ * node with {@value #CHILD_COUNT} existing child nodes.
+ */
+public class UpdateManyChildNodesTest extends AbstractTest {
+
+ private static final int CHILD_COUNT = 10 * 1000;
+
+ private Session session;
+
+ private Node node;
+
+ public void beforeSuite() throws RepositoryException {
+ session = getRepository().login(getCredentials());
+ node = session.getRootNode().addNode("testnode", "nt:unstructured");
+ for (int i = 0; i < CHILD_COUNT; i++) {
+ node.addNode("node" + i, "nt:unstructured");
+ }
+ }
+
+ public void beforeTest() throws RepositoryException {
+ }
+
+ public void runTest() throws Exception {
+ node.addNode("onemore", "nt:unstructured");
+ session.save();
+ }
+
+ public void afterTest() throws RepositoryException {
+ node.getNode("onemore").remove();
+ session.save();
+ }
+
+ public void afterSuite() throws RepositoryException {
+ session.getRootNode().getNode("testnode").remove();
+ session.save();
+ session.logout();
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/SmallFileReadTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/SmallFileReadTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/SmallFileReadTest.java (revision 0)
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import java.io.InputStream;
+import java.util.Calendar;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.NullOutputStream;
+
+public class SmallFileReadTest extends AbstractTest {
+
+ private static final int FILE_COUNT = 1000;
+
+ private static final int FILE_SIZE = 10;
+
+ private Session session;
+
+ private Node root;
+
+ public void beforeSuite() throws RepositoryException {
+ session = getRepository().login(getCredentials());
+
+ root = session.getRootNode().addNode(
+ "SmallFileReadTest", "nt:folder");
+ for (int i = 0; i < FILE_COUNT; i++) {
+ Node file = root.addNode("file" + i, "nt:file");
+ Node content = file.addNode("jcr:content", "nt:resource");
+ content.setProperty("jcr:mimeType", "application/octet-stream");
+ content.setProperty("jcr:lastModified", Calendar.getInstance());
+ content.setProperty(
+ "jcr:data", new TestInputStream(FILE_SIZE * 1024));
+ }
+ session.save();
+ }
+
+ public void runTest() throws Exception {
+ for (int i = 0; i < FILE_COUNT; i++) {
+ Node file = root.getNode("file" + i);
+ Node content = file.getNode("jcr:content");
+ InputStream stream = content.getProperty("jcr:data").getStream();
+ try {
+ IOUtils.copy(stream, new NullOutputStream());
+ } finally {
+ stream.close();
+ }
+ }
+ }
+
+ public void afterSuite() throws RepositoryException {
+ root.remove();
+ session.save();
+ session.logout();
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/SQL2SearchTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/SQL2SearchTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/SQL2SearchTest.java (revision 0)
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+
+public class SQL2SearchTest extends SimpleSearchTest {
+
+ protected Query createQuery(QueryManager manager, int i)
+ throws RepositoryException {
+ return manager.createQuery(
+ "SELECT * FROM [nt:base] WHERE testcount=" + i,
+ "JCR-SQL2");
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/LoginTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/LoginTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/LoginTest.java (revision 0)
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+public class LoginTest extends AbstractTest {
+
+ private final Session[] sessions = new Session[1000];
+
+ @Override
+ public void setUp(Repository repository, Credentials credentials)
+ throws Exception {
+ super.setUp(repository,
+ new SimpleCredentials("admin", "admin".toCharArray()));
+ }
+
+ public void runTest() throws RepositoryException {
+ for (int i = 0; i < sessions.length; i++) {
+ sessions[i] = getRepository().login(getCredentials(), "default");
+ }
+
+ }
+
+ public void afterTest() throws RepositoryException {
+ for (int i = 0; i < sessions.length; i++) {
+ sessions[i].logout();
+ }
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/TestInputStream.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/TestInputStream.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/TestInputStream.java (revision 0)
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import java.io.InputStream;
+import java.util.Random;
+
+/**
+ * An input stream that returns a given number of dummy data. The returned
+ * data is designed to be non-compressible to prevent possible compression
+ * mechanisms from affecting performance measurements.
+ */
+class TestInputStream extends InputStream {
+
+ private final int n;
+
+ private int i;
+
+ /**
+ * Source of the random stream of bytes. No fixed seed is used to
+ * prevent a solution like the Jackrabbit data store from using just
+ * a single storage location for multiple streams.
+ */
+ private final Random random = new Random();
+
+ public TestInputStream(int length) {
+ n = length;
+ i = 0;
+ }
+
+ @Override
+ public int read() {
+ if (i < n) {
+ i++;
+ byte[] b = new byte[1];
+ random.nextBytes(b);
+ return b[0];
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) {
+ if (i < n) {
+ byte[] data = new byte[Math.min(len, n - i)];
+ random.nextBytes(data);
+ System.arraycopy(data, 0, b, off, data.length);
+ i += data.length;
+ return data.length;
+ } else {
+ return -1;
+ }
+ }
+
+
+}
\ No newline at end of file
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/ConcurrentReadTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/ConcurrentReadTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/ConcurrentReadTest.java (revision 0)
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import java.util.Random;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+/**
+ * Test case that traverses 10k unstructured nodes (100x100) while 50 concurrent
+ * readers randomly access nodes from within this tree.
+ */
+public class ConcurrentReadTest extends AbstractTest {
+
+ protected static final int NODE_COUNT = 100;
+
+ private static final int READER_COUNT = getScale(20);
+
+ private Session session;
+
+ protected Node root;
+
+ public void beforeSuite() throws Exception {
+ session = getRepository().login(
+ new SimpleCredentials("admin", "admin".toCharArray()));
+ root = session.getRootNode().addNode("testroot", "nt:unstructured");
+ for (int i = 0; i < NODE_COUNT; i++) {
+ Node node = root.addNode("node" + i, "nt:unstructured");
+ for (int j = 0; j < NODE_COUNT; j++) {
+ node.addNode("node" + j, "nt:unstructured");
+ }
+ session.save();
+ }
+
+ for (int i = 0; i < READER_COUNT; i++) {
+ addBackgroundJob(new Reader());
+ }
+ }
+
+ private class Reader implements Runnable {
+
+ private Session session;
+
+ private final Random random = new Random();
+
+ public void run() {
+
+ try {
+ session = getRepository().login(
+ new SimpleCredentials("admin", "admin".toCharArray()));
+ 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 runTest() throws Exception {
+ Reader reader = new Reader();
+ for (int i = 0; i < 1000; i++) {
+ reader.run();
+ }
+ }
+
+ public void afterSuite() throws Exception {
+ for (int i = 0; i < NODE_COUNT; i++) {
+ root.getNode("node" + i).remove();
+ session.save();
+ }
+
+ root.remove();
+ session.save();
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/SimpleSearchTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/SimpleSearchTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/SimpleSearchTest.java (revision 0)
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+
+public class SimpleSearchTest extends AbstractTest {
+
+ private static final int NODE_COUNT = 100;
+
+ private Session session;
+
+ private Node root;
+
+ protected Query createQuery(QueryManager manager, int i)
+ throws RepositoryException {
+ return manager.createQuery("//*[@testcount=" + i + "]", Query.XPATH);
+ }
+
+ public void beforeSuite() throws RepositoryException {
+ session = getRepository().login(getCredentials());
+
+ root = session.getRootNode().addNode("testroot", "nt:unstructured");
+ for (int i = 0; i < NODE_COUNT; i++) {
+ Node node = root.addNode("node" + i, "nt:unstructured");
+ for (int j = 0; j < NODE_COUNT; j++) {
+ Node child = node.addNode("node" + j, "nt:unstructured");
+ child.setProperty("testcount", j);
+ }
+ session.save();
+ }
+ }
+
+ public void runTest() throws Exception {
+ QueryManager manager = session.getWorkspace().getQueryManager();
+ for (int i = 0; i < NODE_COUNT; i++) {
+ Query query = createQuery(manager, i);
+ NodeIterator iterator = query.execute().getNodes();
+ while (iterator.hasNext()) {
+ Node node = iterator.nextNode();
+ if (node.getProperty("testcount").getLong() != i) {
+ throw new Exception("Invalid test result: " + node.getPath());
+ }
+ }
+ }
+ }
+
+ public void afterSuite() throws RepositoryException {
+ for (int i = 0; i < NODE_COUNT; i++) {
+ root.getNode("node" + i).remove();
+ session.save();
+ }
+
+ root.remove();
+ session.save();
+ session.logout();
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/ReadPropertyTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/ReadPropertyTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/ReadPropertyTest.java (revision 0)
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+/**
+ * ReadPropertyTest implements a performance test, which reads
+ * three properties: one with a jcr prefix, one with the empty prefix and a
+ * third one, which does not exist.
+ */
+public class ReadPropertyTest extends AbstractTest {
+
+ private Session session;
+
+ private Node root;
+
+ @Override
+ protected void beforeSuite() throws Exception {
+ session = getRepository().login(getCredentials());
+ root = session.getRootNode().addNode(
+ getClass().getSimpleName(), "nt:unstructured");
+ root.setProperty("property", "value");
+ session.save();
+ }
+
+ @Override
+ protected void runTest() throws Exception {
+ for (int i = 0; i < 10000; i++) {
+ root.getProperty("jcr:primaryType");
+ root.getProperty("property");
+ root.hasProperty("does-not-exist");
+ }
+ }
+
+ @Override
+ protected void afterSuite() throws Exception {
+ root.remove();
+ session.save();
+ session.logout();
+ }
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/SmallFileWriteTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/SmallFileWriteTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/SmallFileWriteTest.java (revision 0)
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import java.util.Calendar;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+public class SmallFileWriteTest extends AbstractTest {
+
+ private static final int FILE_COUNT = 100;
+
+ private static final int FILE_SIZE = 10;
+
+ private Session session;
+
+ private Node root;
+
+ public void beforeSuite() throws RepositoryException {
+ session = loginWriter();
+ }
+
+ public void beforeTest() throws RepositoryException {
+ root = session.getRootNode().addNode("SmallFileWriteTest", "nt:folder");
+ session.save();
+ }
+
+ public void runTest() throws Exception {
+ for (int i = 0; i < FILE_COUNT; i++) {
+ Node file = root.addNode("file" + i, "nt:file");
+ Node content = file.addNode("jcr:content", "nt:resource");
+ content.setProperty("jcr:mimeType", "application/octet-stream");
+ content.setProperty("jcr:lastModified", Calendar.getInstance());
+ content.setProperty(
+ "jcr:data", new TestInputStream(FILE_SIZE * 1024));
+ }
+ session.save();
+ }
+
+ public void afterTest() throws RepositoryException {
+ root.remove();
+ session.save();
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/CreateManyChildNodesTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/CreateManyChildNodesTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/CreateManyChildNodesTest.java (revision 0)
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * Test for measuring the performance of creating a node with
+ * {@value #CHILD_COUNT} child nodes.
+ */
+public class CreateManyChildNodesTest extends AbstractTest {
+
+ private static final int CHILD_COUNT = 10 * 1000;
+
+ private Session session;
+
+ public void beforeSuite() throws RepositoryException {
+ session = loginWriter();
+ }
+
+ public void beforeTest() throws RepositoryException {
+ }
+
+ public void runTest() throws Exception {
+ Node node = session.getRootNode().addNode("testnode", "nt:unstructured");
+ for (int i = 0; i < CHILD_COUNT; i++) {
+ node.addNode("node" + i, "nt:unstructured");
+ }
+ session.save();
+ }
+
+ public void afterTest() throws RepositoryException {
+ session.getRootNode().getNode("testnode").remove();
+ session.save();
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/AbstractPerformanceTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/AbstractPerformanceTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/AbstractPerformanceTest.java (revision 0)
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.regex.Pattern;
+
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.commons.io.output.FileWriterWithEncoding;
+import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
+import org.apache.jackrabbit.oak.jcr.RepositoryImpl;
+
+public abstract class AbstractPerformanceTest {
+
+ private final int warmup = 1;
+
+ private final int runtime = 10;
+
+ private final Credentials credentials = new SimpleCredentials("admin",
+ "admin".toCharArray());
+
+ private final Pattern microKernelPattern = Pattern.compile(System
+ .getProperty("mk", ".*"));
+ private final Pattern testPattern = Pattern.compile(System.getProperty(
+ "only", ".*"));
+
+ protected void testPerformance(String name, String microKernel)
+ throws Exception {
+
+ runTest(new LoginTest(), name, microKernel);
+ runTest(new LoginLogoutTest(), name, microKernel);
+ runTest(new ReadPropertyTest(), name, microKernel);
+ runTest(new SetPropertyTest(), name, microKernel);
+ runTest(new SmallFileReadTest(), name, microKernel);
+ runTest(new SmallFileWriteTest(), name, microKernel);
+ runTest(new ConcurrentReadTest(), name, microKernel);
+ runTest(new ConcurrentReadWriteTest(), name, microKernel);
+ runTest(new SimpleSearchTest(), name, microKernel);
+ runTest(new SQL2SearchTest(), name, microKernel);
+ runTest(new DescendantSearchTest(), name, microKernel);
+ runTest(new SQL2DescendantSearchTest(), name, microKernel);
+ runTest(new CreateManyChildNodesTest(), name, microKernel);
+ runTest(new UpdateManyChildNodesTest(), name, microKernel);
+ runTest(new TransientManyChildNodesTest(), name, microKernel);
+
+ }
+
+ private void runTest(AbstractTest test, String name, String microKernel) {
+ if (microKernelPattern.matcher(microKernel).matches()
+ && testPattern.matcher(test.toString()).matches()) {
+
+ RepositoryImpl repository;
+ try {
+ repository = createRepository(microKernel);
+
+ // Run the test
+ DescriptiveStatistics statistics = runTest(test, repository);
+ if (statistics.getN() > 0) {
+ writeReport(test.toString(), name, microKernel, statistics);
+ }
+ } catch (RepositoryException re) {
+ re.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private DescriptiveStatistics runTest(AbstractTest test,
+ Repository repository) throws Exception {
+ DescriptiveStatistics statistics = new DescriptiveStatistics();
+
+ test.setUp(repository, credentials);
+ try {
+ // Run a few iterations to warm up the system
+ long warmupEnd = System.currentTimeMillis() + warmup * 1000;
+ while (System.currentTimeMillis() < warmupEnd) {
+ test.execute();
+ }
+
+ // Run test iterations, and capture the execution times
+ long runtimeEnd = System.currentTimeMillis() + runtime * 1000;
+ while (System.currentTimeMillis() < runtimeEnd) {
+ statistics.addValue(test.execute());
+ }
+ } finally {
+ test.tearDown();
+ }
+
+ return statistics;
+ }
+
+ private void writeReport(String test, String name, String microKernel,
+ DescriptiveStatistics statistics) throws IOException {
+ File report = new File("target", test + "-" + microKernel + ".txt");
+
+ boolean needsPrefix = !report.exists();
+ PrintWriter writer = new PrintWriter(new FileWriterWithEncoding(report,
+ "UTF-8", true));
+ try {
+ if (needsPrefix) {
+ writer.format(
+ "# %-34.34s min 10%% 50%% 90%% max%n",
+ test);
+ }
+
+ writer.format("%-36.36s %6.0f %6.0f %6.0f %6.0f %6.0f%n",
+ name, statistics.getMin(), statistics.getPercentile(10.0),
+ statistics.getPercentile(50.0),
+ statistics.getPercentile(90.0), statistics.getMax());
+ } finally {
+ writer.close();
+ }
+ }
+
+ protected RepositoryImpl createRepository(String microKernel)
+ throws RepositoryException {
+
+ // TODO: depending on the microKernel string a particular repository
+ // with that MK must be returned
+
+ return new RepositoryImpl();
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/ConcurrentReadWriteTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/ConcurrentReadWriteTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/ConcurrentReadWriteTest.java (revision 0)
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import java.util.Random;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+/**
+ * A {@link ConcurrentReadTest} with a single writer thread that continuously
+ * updates the nodes being accessed by the readers.
+ */
+public class ConcurrentReadWriteTest extends ConcurrentReadTest {
+
+ public void beforeSuite() throws Exception {
+ super.beforeSuite();
+
+ addBackgroundJob(new Writer());
+ }
+
+ private class Writer implements Runnable {
+
+ private Session session;
+
+ private final Random random = new Random();
+
+ private long count = 0;
+
+ public void run() {
+ try {
+ session = getRepository().login(
+ new SimpleCredentials("admin", "admin".toCharArray()));
+ 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);
+ }
+ }
+
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/TransientManyChildNodesTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/TransientManyChildNodesTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/TransientManyChildNodesTest.java (revision 0)
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * Test for measuring the performance of {@value #ITERATIONS} iterations of
+ * transiently adding and removing a child node to a node that already has
+ * {@value #CHILD_COUNT} existing child nodes.
+ */
+public class TransientManyChildNodesTest extends AbstractTest {
+
+ private static final int CHILD_COUNT = 10 * 1000;
+
+ private static final int ITERATIONS = 1000;
+
+ private Session session;
+
+ private Node node;
+
+ public void beforeSuite() throws RepositoryException {
+ session = getRepository().login(getCredentials());
+ node = session.getRootNode().addNode("testnode", "nt:unstructured");
+ for (int i = 0; i < CHILD_COUNT; i++) {
+ node.addNode("node" + i, "nt:unstructured");
+ }
+ }
+
+ public void beforeTest() throws RepositoryException {
+ }
+
+ public void runTest() throws Exception {
+ for (int i = 0; i < ITERATIONS; i++) {
+ node.addNode("onemore", "nt:unstructured").remove();
+ }
+ }
+
+ public void afterTest() throws RepositoryException {
+ }
+
+ public void afterSuite() throws RepositoryException {
+ session.getRootNode().getNode("testnode").remove();
+ session.save();
+ session.logout();
+ }
+
+}
Index: base/src/main/java/org/apache/jackrabbit/oak/performance/DescendantSearchTest.java
===================================================================
--- base/src/main/java/org/apache/jackrabbit/oak/performance/DescendantSearchTest.java (revision 0)
+++ base/src/main/java/org/apache/jackrabbit/oak/performance/DescendantSearchTest.java (revision 0)
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+
+/**
+ * Performance test to check performance of queries on sub-trees.
+ */
+public class DescendantSearchTest extends AbstractTest {
+
+ private static final int NODE_COUNT = 100;
+
+ private Session session;
+
+ private Node root;
+
+ protected Query createQuery(QueryManager manager, int i)
+ throws RepositoryException {
+ return manager.createQuery("/jcr:root/testroot//element(*,nt:base)[@testcount=" + i + "]", Query.XPATH);
+ }
+
+ public void beforeSuite() throws RepositoryException {
+ session = getRepository().login(getCredentials());
+
+ root = session.getRootNode().addNode("testroot", "nt:unstructured");
+ for (int i = 0; i < NODE_COUNT; i++) {
+ Node node = root.addNode("node" + i, "nt:unstructured");
+ for (int j = 0; j < NODE_COUNT; j++) {
+ Node child = node.addNode("node" + j, "nt:unstructured");
+ child.setProperty("testcount", j);
+ }
+ session.save();
+ }
+ }
+
+ public void runTest() throws Exception {
+ QueryManager manager = session.getWorkspace().getQueryManager();
+ for (int i = 0; i < NODE_COUNT; i++) {
+ Query query = createQuery(manager, i);
+ NodeIterator iterator = query.execute().getNodes();
+ while (iterator.hasNext()) {
+ Node node = iterator.nextNode();
+ if (node.getProperty("testcount").getLong() != i) {
+ throw new Exception("Invalid test result: " + node.getPath());
+ }
+ }
+ }
+ }
+
+ public void afterSuite() throws RepositoryException {
+ for (int i = 0; i < NODE_COUNT; i++) {
+ root.getNode("node" + i).remove();
+ session.save();
+ }
+
+ root.remove();
+ session.save();
+ session.logout();
+ }
+
+}
Index: base/pom.xml
===================================================================
--- base/pom.xml (revision 0)
+++ base/pom.xml (revision 0)
@@ -0,0 +1,83 @@
+
+
+
+
+
+ 4.0.0
+
+
+ org.apache.jackrabbit.oak
+ oak-perf-parent
+ 1-SNAPSHOT
+ ../parent/pom.xml
+
+
+ oak-perf-base
+ Oak Performance Test Utilities
+
+
+
+ javax.jcr
+ jcr
+ 2.0
+
+
+ org.apache.commons
+ commons-math
+ 2.0
+
+
+ org.apache.jackrabbit
+ oak-jcr
+ 0.3-SNAPSHOT
+ provided
+
+
+
+
+ commons-io
+ commons-io
+ 1.4
+
+
+ org.slf4j
+ slf4j-api
+ 1.5.8
+
+
+ org.slf4j
+ slf4j-nop
+ 1.5.8
+
+
+ org.testng
+ testng
+ jdk15
+ 5.8
+
+
+
+
+
Index: pom.xml
===================================================================
--- pom.xml (revision 0)
+++ pom.xml (revision 0)
@@ -0,0 +1,47 @@
+
+
+
+
+
+ 4.0.0
+
+
+
+
+
+
+ org.apache.jackrabbit.oak
+ oak-perf-parent
+ 1-SNAPSHOT
+ parent/pom.xml
+
+
+ oak-perf
+ Oak Performance Tests
+ pom
+
+
+ parent
+ base
+ oak03
+
+
+
Index: README.txt
===================================================================
--- README.txt (revision 0)
+++ README.txt (revision 0)
@@ -0,0 +1,85 @@
+---------------------------------
+Oak Performance Test Suite
+---------------------------------
+
+This directory contains a simple performance test suite that can be
+extended for ongoing Oak versions and micro kernels. Use the following
+command to run this test suite:
+
+ mvn clean install
+
+Note that the test suite will take more than an hour to complete, and to
+avoid distorting the results you should avoid putting any extra load on
+the computer while the test suite is running.
+
+The results are stored as oak*/target/*.txt report files and can
+be combined into an HTML report by running the following command on a
+(Unix) system where gnuplot is installed.
+
+ sh plot.sh
+
+Mac OS X note : if you want to execute the above script, you will need
+to install gnuplot and imagemagick2-svg from the Fink project. For
+more information : http://finkproject.org
+
+Selecting which tests to run
+----------------------------
+
+The -Donly command line parameter allows you to specify a regexp for
+selecting which performance test cases to run. To run a single test
+case, use a command like this:
+
+ mvn clean install -Donly=ConcurrentReadTest
+
+To run all concurrency tests, use:
+
+ mvn clean install -Donly=Concurrent.*Test
+
+Selecting which micro kernel to test
+----------------------------------------------------------
+
+The -Dmk command line parameter allows you to specify a regexp for
+selecting the micro kernel and configurations against which the
+performance tests are run. The default setting selects only the default
+micro kernel:
+
+ mvn clean install -Dmk=\d\.\d
+
+To run the tests against all included configurations, use:
+
+ mvn clean install -Dmk=.*
+
+Using a profiler
+----------------
+
+To enable a profiler, use the -Dagentlib= command line pameter:
+
+ mvn clean install -Dagentlib=hprof=cpu=samples,depth=10
+
+Adding a new performance test
+-----------------------------
+
+The tests run by this performance test suite are listed in the
+testPerformance() method of the AbstractPerformanceTest class in
+the org.apache.jackrabbit.oak.performance package of the oak-perf-base
+component that you can find in the ./base directory.
+
+Each test is a subclass of the AbstractTest class in that same package,
+and you need to implement at least the abstract runTest() method when
+creating a new test. The runTest() method should contain the code whose
+performance you want to measure. For best measurement results the method
+should normally take something between 0.1 to 10 seconds to execute, so
+you may need to add a constant-size loop around your code like is done
+for example in the LoginTest class. The test suite compares relative
+performance between different Oak versions, so the absolute time
+taken by the test method is irrelevant.
+
+Many performance tests need some setup and teardown code for things like
+building the content tree against which the test is being run. Such work
+should not be included in the runTest() method to prevent affecting the
+performance measurements. Instead you can override the before/afterTest()
+and before/afterSuite() methods that get called respectively before and
+after each individual test iteration and the entire test suite. See for
+example the SetPropertyTest class for an example of how these methods
+are best used.
+
Index: oak03/src/test/java/org/apache/jackrabbit/oak/performance/PerformanceTest.java
===================================================================
--- oak03/src/test/java/org/apache/jackrabbit/oak/performance/PerformanceTest.java (revision 0)
+++ oak03/src/test/java/org/apache/jackrabbit/oak/performance/PerformanceTest.java (revision 0)
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.performance;
+
+import org.apache.jackrabbit.oak.performance.AbstractPerformanceTest;
+import org.testng.annotations.Test;
+
+public class PerformanceTest extends AbstractPerformanceTest {
+
+ @Test
+ public void testPerformance() throws Exception {
+ testPerformance("0.3", "default");
+ testPerformance("0.3", "other_mk");
+ }
+}
Index: oak03/pom.xml
===================================================================
--- oak03/pom.xml (revision 0)
+++ oak03/pom.xml (revision 0)
@@ -0,0 +1,64 @@
+
+
+
+
+
+ 4.0.0
+
+
+ org.apache.jackrabbit.oak
+ oak-perf-parent
+ 1-SNAPSHOT
+ ../parent/pom.xml
+
+
+ oak-perf-oak03
+ Oak 0.3 Performance Test
+
+
+
+ org.apache.jackrabbit.oak
+ oak-perf-base
+ ${project.version}
+ test
+
+
+ javax.jcr
+ jcr
+ 2.0
+ test
+
+
+ org.apache.jackrabbit
+ oak-jcr
+ 0.3-SNAPSHOT
+ provided
+
+
+
+
+
+