Author: mreutegg
Date: Thu Jul 16 08:57:53 2015
New Revision: 1691340
URL: http://svn.apache.org/r1691340
Log:
OAK-3112: Performance degradation of UnsavedModifications on MapDB
Add a long running test, which shows the degradation (ignored).
Modified:
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java
Modified:
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java?rev=1691340&r1=1691339&r2=1691340&view=diff
==============================================================================
---
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java
(original)
+++
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java
Thu Jul 16 08:57:53 2015
@@ -66,15 +66,24 @@ class UnsavedModifications implements Cl
/**
* The map factory for this instance.
*/
- private final MapFactory mapFactory = MapFactory.createFactory();
+ private final MapFactory mapFactory;
- private final ConcurrentMap<String, Revision> map = mapFactory.create();
+ private final ConcurrentMap<String, Revision> map;
/**
* Monitor object to synchronize updates on the {@link #map}. See OAK-2888.
*/
private final Object update = new Object();
+ public UnsavedModifications() {
+ this(MapFactory.createFactory());
+ }
+
+ UnsavedModifications(MapFactory mapFactory) {
+ this.mapFactory = mapFactory;
+ this.map = mapFactory.create();
+ }
+
/**
* Puts a revision for the given path. The revision for the given path is
* only put if there is no modification present for the revision or if the
Modified:
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java?rev=1691340&r1=1691339&r2=1691340&view=diff
==============================================================================
---
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java
(original)
+++
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java
Thu Jul 16 08:57:53 2015
@@ -20,17 +20,24 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
+import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Sets;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
+import org.apache.jackrabbit.oak.plugins.document.util.MapDBMapFactory;
+import org.apache.jackrabbit.oak.plugins.document.util.MapFactory;
import org.junit.Ignore;
import org.junit.Test;
-/**
- * Test for OAK-2888
- */
public class UnsavedModificationsTest {
+ private static final String CHARS = "abcdefghijklmnopqrstuvwxyz";
+
+ // OAK-2888
@Test
public void concurrent() throws Exception {
final List<Exception> exceptions = Collections.synchronizedList(
@@ -115,4 +122,78 @@ public class UnsavedModificationsTest {
}
}
+ // OAK-3112
+ @Ignore
+ @Test
+ public void performance() throws Exception {
+ DocumentStore store = new MemoryDocumentStore() {
+ @Override
+ public <T extends Document> void update(Collection<T> collection,
+ List<String> keys,
+ UpdateOp updateOp) {
+ // ignore call
+ }
+ };
+ final DocumentNodeStore ns = new
DocumentMK.Builder().setDocumentStore(store)
+ .getNodeStore();
+
+ // MapFactory factory = MapFactory.getInstance();
+ MapFactory factory = new MapDBMapFactory();
+ final UnsavedModifications pending = new UnsavedModifications(factory);
+
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ Random random = new Random(42);
+ Set<String> paths = Sets.newHashSet();
+ int num = 0;
+ for (int i = 0; i < 1000; i++) {
+ String n1 = randomName(random, 20);
+ for (int j = 0; j < 100; j++) {
+ String n2 = randomName(random, 20);
+ for (int k = 0; k < 100; k++) {
+ num++;
+ String n3 = randomName(random, 20);
+ paths.add("/");
+ paths.add(PathUtils.concat("/", n1));
+ paths.add(PathUtils.concat("/", n1, n2));
+ paths.add(PathUtils.concat("/", n1, n2, n3));
+ if (paths.size() >= 20) {
+ Revision r = new Revision(num, 0, 1);
+ for (String p : paths) {
+ pending.put(p, r);
+ }
+ paths.clear();
+ }
+ if (num % 1000 == 0) {
+ pending.persist(ns, new ReentrantLock());
+ }
+ }
+ }
+ }
+ }
+ });
+ t.start();
+
+ Set<String> keys = Sets.newHashSet();
+ while (t.isAlive()) {
+ keys.clear();
+ Stopwatch sw = Stopwatch.createStarted();
+ keys.addAll(pending.getPaths());
+ sw.stop();
+ System.out.println(keys.size() + " keys in " + sw);
+ keys.clear();
+ Thread.sleep(1000);
+ }
+ pending.close();
+ ns.dispose();
+ }
+
+ private static String randomName(Random r, int len) {
+ StringBuilder sb = new StringBuilder(len);
+ for (int i = 0; i < len; i++) {
+ sb.append(CHARS.charAt(r.nextInt(CHARS.length())));
+ }
+ return sb.toString();
+ }
}