OAK-9158: Performance issue due to AbstractDocumentNodeState#equals
Patch provided by Alexander Lüders
Added test to reproduce the problem
git-svn-id: https://svn.apache.org/repos/asf/jackrabbit/oak/trunk@1886954 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/AbstractDocumentNodeState.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/AbstractDocumentNodeState.java
index bfa71c5..8ac92d8 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/AbstractDocumentNodeState.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/AbstractDocumentNodeState.java
@@ -83,7 +83,11 @@
// revision does not match: might still be equals
} else if (that instanceof ModifiedNodeState) {
ModifiedNodeState modified = (ModifiedNodeState) that;
- if (modified.getBaseState() == this) {
+ NodeState baseState = modified.getBaseState();
+ if (baseState instanceof ModifiedDocumentNodeState) {
+ baseState = ((ModifiedDocumentNodeState) baseState).getBaseState();
+ }
+ if (baseState == this) {
return EqualsDiff.equals(this, modified);
}
}
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ModifiedDocumentNodeState.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ModifiedDocumentNodeState.java
index 8dbfb03..4dabeb2 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ModifiedDocumentNodeState.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ModifiedDocumentNodeState.java
@@ -142,6 +142,10 @@
return super.compareAgainstBaseState(base, diff);
}
+ NodeState getBaseState() {
+ return base;
+ }
+
private boolean revisionEquals(AbstractDocumentNodeState a,
AbstractDocumentNodeState b) {
RevisionVector rv1 = a.getLastRevision();
diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
index ba66ce4..dad8bad 100644
--- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
+++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
@@ -35,8 +35,10 @@
import static org.apache.jackrabbit.oak.plugins.document.util.Utils.isCommitted;
import static org.hamcrest.CoreMatchers.everyItem;
import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -44,7 +46,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -789,7 +790,7 @@
assertNotNull(afterRootDoc);
Revision afterLastRev = afterRootDoc.getLastRev().get(clusterId);
- assertThat("lastRev must be greater or equal '" + Utils.timestampToString(timeBeforeStartup) + "', but was '"
+ assertThat("lastRev must be greater or equal '" + Utils.timestampToString(timeBeforeStartup) + "', but was '"
+ Utils.timestampToString(afterLastRev.getTimestamp()) + "'", afterLastRev.getTimestamp(),
OrderingComparison.greaterThanOrEqualTo(timeBeforeStartup));
assertNotEquals("Last revision should be updated after 1 minute even if background thread is not running",
@@ -4092,6 +4093,35 @@
}
// End of tests for OAK-9300
+ @Test // OAK-9158
+ public void manyNodesBelowRoot() throws Exception {
+ CountingDocumentStore store = new CountingDocumentStore(new MemoryDocumentStore());
+ DocumentNodeStore ns = builderProvider.newBuilder()
+ .setBundlingDisabled(true)
+ .setDocumentStore(store).setAsyncDelay(0)
+ .getNodeStore();
+ NodeBuilder builder = ns.getRoot().builder();
+ for (int i = 0; i < 250; i++) {
+ builder.child("node-" + i);
+ }
+ merge(ns, builder);
+ ns.dispose();
+ store.resetCounters();
+
+ ns = builderProvider.newBuilder()
+ .setBundlingDisabled(true)
+ .setDocumentStore(store).setAsyncDelay(0).setUpdateLimit(5)
+ .getNodeStore();
+
+ builder = ns.getRoot().builder();
+ for (int i = 0; i < 10; i++) {
+ builder.child("foo").setProperty("p", i);
+ }
+ merge(ns, builder);
+ assertThat(store.getNumFindCalls(NODES), lessThan(10));
+ assertEquals(0, store.getNumQueryCalls(NODES));
+ }
+
private void getChildNodeCountTest(int numChildren,
Iterable<Long> maxValues,
Iterable<Long> expectedValues)