diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCache.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCache.java index 60d5fd5..09b2556 100644 --- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCache.java +++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCache.java @@ -27,6 +27,7 @@ import com.google.common.base.Supplier; import com.google.common.cache.CacheStats; +import com.google.common.cache.Weigher; /** * Partial mapping of keys of type {@code T} to values of type {@link RecordId}. This is @@ -56,6 +57,8 @@ */ public abstract long size(); + public abstract long estimateCurrentWeight(); + /** * @return access statistics for this cache */ @@ -76,7 +79,7 @@ if (size <= 0) { return new Empty<>(); } else { - return new Default<>(size); + return new Default<>(size, null); } } @@ -86,11 +89,11 @@ * @see #newRecordCache(int) */ @Nonnull - public static Supplier> factory(int size) { + public static Supplier> factory(int size, Weigher weigher) { if (size <= 0) { return Empty.emptyFactory(); } else { - return Default.defaultFactory(size); + return Default.defaultFactory(size, weigher); } } @@ -117,27 +120,40 @@ public long size() { return 0; } + + @Override + public long estimateCurrentWeight() { + return -1; + } } private static class Default extends RecordCache { private final Map records; - static final Supplier> defaultFactory(final int size) { + private final Weigher weigher; + private long weight = -1; + + static final Supplier> defaultFactory(final int size, final Weigher weigher) { return new Supplier>() { @Override public RecordCache get() { - return new Default<>(size); + return new Default<>(size, weigher); } }; } - Default(final int size) { + Default(final int size, final Weigher weigher) { + this.weigher = weigher; records = new LinkedHashMap(size * 4 / 3, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { boolean remove = super.size() > size; if (remove) { Default.super.evictionCount++; + if (weigher != null) { + weight -= weigher.weigh(eldest.getKey(), + eldest.getValue()); + } } return remove; } @@ -148,6 +164,9 @@ public synchronized void put(@Nonnull T key, @Nonnull RecordId value) { super.loadCount++; records.put(key, value); + if (weigher != null) { + weight += weigher.weigh(key, value); + } } @Override @@ -165,5 +184,10 @@ public synchronized long size() { return records.size(); } + + @Override + public long estimateCurrentWeight() { + return weight; + } } } diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCacheStats.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCacheStats.java index aa4914f..d42a4a5 100644 --- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCacheStats.java +++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCacheStats.java @@ -47,14 +47,19 @@ @Nonnull private final Supplier elementCount; + @Nonnull + private final Supplier weight; + private CacheStats lastSnapshot; - public RecordCacheStats( - @Nonnull String name, @Nonnull Supplier stats, @Nonnull Supplier elementCount) { + public RecordCacheStats(@Nonnull String name, + @Nonnull Supplier stats, + @Nonnull Supplier elementCount, @Nonnull Supplier weight) { super(CacheStatsMBean.class); this.name = checkNotNull(name); this.stats = checkNotNull(stats); this.elementCount = checkNotNull(elementCount); + this.weight = checkNotNull(weight); this.lastSnapshot = stats.get(); } @@ -145,7 +150,7 @@ @Override public long estimateCurrentWeight() { - return -1; + return weight.get(); } @Override diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordId.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordId.java index f4b476a..882be9f 100644 --- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordId.java +++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordId.java @@ -18,17 +18,16 @@ */ package org.apache.jackrabbit.oak.segment; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static java.lang.Integer.parseInt; -import static org.apache.jackrabbit.oak.segment.Segment.RECORD_ALIGN_BITS; -import static org.apache.jackrabbit.oak.segment.Segment.RECORD_ID_BYTES; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Nonnull; + +import org.apache.jackrabbit.oak.commons.StringUtils; /** * The record id. This includes the segment id and the offset within the @@ -150,4 +149,10 @@ } } + public int estimateMemoryUsage() { + int size = 112; + size += StringUtils.estimateMemoryUsage(getSegmentId().getGcInfo()); + return size; + } + } diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Template.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Template.java index 2055f28..45b3411 100644 --- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Template.java +++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Template.java @@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkElementIndex; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import static org.apache.jackrabbit.oak.api.Type.STRING; import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.MISSING_NODE; import static org.apache.jackrabbit.oak.segment.Segment.RECORD_ID_BYTES; @@ -36,6 +37,7 @@ import com.google.common.collect.Lists; import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Type; +import org.apache.jackrabbit.oak.commons.StringUtils; import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry; import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry; import org.apache.jackrabbit.oak.spi.state.NodeState; @@ -347,4 +349,39 @@ } } + public int estimateMemoryUsage() { + int size = 4; + size += estimateMemoryUsage(getPrimaryType()); + size += estimateMemoryUsage(getMixinTypes()); + size += estimateMemoryUsage(getChildName()); + for (PropertyTemplate property : getPropertyTemplates()) { + size += estimateMemoryUsage(property); + } + return size; + } + + private static int estimateMemoryUsage(PropertyTemplate propertyTemplate) { + return 4 + // index + estimateMemoryUsage(propertyTemplate.getName()); + } + + private static int estimateMemoryUsage(PropertyState propertyState) { + if (propertyState == null) { + return 0; + } + + int size = estimateMemoryUsage(propertyState.getName()); + for (int k = 0; k < propertyState.count(); k++) { + size += estimateMemoryUsage(propertyState.getValue(STRING, k)); + } + return size; + } + + private static int estimateMemoryUsage(String string) { + if (string == null) { + return 0; + } + return StringUtils.estimateMemoryUsage(string); + } + } diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/TemplateCache.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/TemplateCache.java index 8b45545..aa724fe 100644 --- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/TemplateCache.java +++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/TemplateCache.java @@ -19,10 +19,7 @@ package org.apache.jackrabbit.oak.segment; -import static org.apache.jackrabbit.oak.api.Type.STRING; - import org.apache.jackrabbit.oak.api.PropertyState; -import org.apache.jackrabbit.oak.commons.StringUtils; public class TemplateCache extends ReaderCache