You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by mr...@apache.org on 2013/03/04 11:46:57 UTC
svn commit: r1452248 - in
/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel:
KernelNodeState.java KernelNodeStore.java
Author: mreutegg
Date: Mon Mar 4 10:46:57 2013
New Revision: 1452248
URL: http://svn.apache.org/r1452248
Log:
OAK-643: Very high memory usage with 6000 child nodes
- limit cache size by memory using a Weigher
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java?rev=1452248&r1=1452247&r2=1452248&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java Mon Mar 4 10:46:57 2013
@@ -152,6 +152,10 @@ public final class KernelNodeState exten
initialized = true;
}
}
+ if (initialized) {
+ // refresh cache to force re-calculation of weight (OAK-643)
+ cache.refresh(revision + path);
+ }
if (initialized && !PathUtils.denotesRoot(path)) {
// OAK-591: check if we can re-use a previous revision
// by looking up the node state by hash or id (if available)
@@ -344,6 +348,46 @@ public final class KernelNodeState exten
return path;
}
+ /**
+ * @return the approximate memory usage of this node state.
+ */
+ synchronized int getMemory() {
+ // base memory footprint is roughly 64 bytes
+ int memory = 64;
+ // path String
+ memory += 12 + path.length() * 2;
+ // revision String
+ memory += 12 + revision.length() * 2;
+ // optional hash String
+ if (hash != null) {
+ memory += 12 + hash.length() * 2;
+ }
+ // optional id String
+ if (id != null && !id.equals(hash)) {
+ memory += 12 + id.length() * 2;
+ }
+ // rough approximation for properties
+ if (properties != null) {
+ for (Map.Entry<String, PropertyState> entry : properties.entrySet()) {
+ // name
+ memory += 12 + entry.getKey().length() * 2;
+ PropertyState propState = entry.getValue();
+ if (propState.getType() != Type.BINARY
+ && propState.getType() != Type.BINARIES) {
+ // assume binaries go into blob store
+ for (int i = 0; i < propState.count(); i++) {
+ memory += propState.size(i);
+ }
+ }
+ }
+ }
+ // rough approximation for child nodes
+ if (childNames != null) {
+ memory += childNames.size() * 150;
+ }
+ return memory;
+ }
+
//------------------------------------------------------------< private >---
private boolean hasChanges(String journal) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java?rev=1452248&r1=1452247&r2=1452248&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java Mon Mar 4 10:46:57 2013
@@ -25,6 +25,10 @@ import javax.annotation.Nonnull;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
+import com.google.common.cache.Weigher;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
import org.apache.jackrabbit.mk.api.MicroKernel;
import org.apache.jackrabbit.mk.api.MicroKernelException;
import org.apache.jackrabbit.oak.spi.commit.EmptyObserver;
@@ -52,17 +56,33 @@ public class KernelNodeStore implements
private volatile Observer observer = EmptyObserver.INSTANCE;
private final LoadingCache<String, KernelNodeState> cache =
- CacheBuilder.newBuilder().maximumSize(10000).build(
- new CacheLoader<String, KernelNodeState>() {
- @Override
- public KernelNodeState load(String key) {
- int slash = key.indexOf('/');
- String revision = key.substring(0, slash);
- String path = key.substring(slash);
- return new KernelNodeState(
- kernel, path, revision, cache);
- }
- });
+ CacheBuilder.newBuilder().maximumWeight(16 * 1024 * 1024).weigher(
+ new Weigher<String, KernelNodeState>() {
+ @Override
+ public int weigh(String key, KernelNodeState state) {
+ return state.getMemory();
+ }
+ }).build(new CacheLoader<String, KernelNodeState>() {
+ @Override
+ public KernelNodeState load(String key) {
+ int slash = key.indexOf('/');
+ String revision = key.substring(0, slash);
+ String path = key.substring(slash);
+ return new KernelNodeState(kernel, path, revision, cache);
+ }
+
+ @Override
+ public ListenableFuture<KernelNodeState> reload(String key,
+ KernelNodeState oldValue)
+ throws Exception {
+ // LoadingCache.reload() is only used to re-calculate the
+ // memory usage on KernelNodeState.init(). Therefore
+ // we simply return the old value as is (OAK-643)
+ SettableFuture<KernelNodeState> future = SettableFuture.create();
+ future.set(oldValue);
+ return future;
+ }
+ });
/**
* State of the current root node.