Index: src/main/java/org/apache/jackrabbit/oak/plugins/segment/StringCache.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/plugins/segment/StringCache.java (revision 1725882) +++ src/main/java/org/apache/jackrabbit/oak/plugins/segment/StringCache.java (working copy) @@ -19,14 +19,17 @@ package org.apache.jackrabbit.oak.plugins.segment; +import static org.apache.jackrabbit.oak.commons.StringUtils.estimateMemoryUsage; + import java.util.Arrays; import javax.annotation.Nonnull; -import com.google.common.base.Function; import org.apache.jackrabbit.oak.cache.CacheLIRS; import org.apache.jackrabbit.oak.cache.CacheStats; +import com.google.common.base.Function; + /** * A string cache. It has two components: a fast cache for small strings, based * on an array, and a slow cache that uses a LIRS cache. @@ -41,7 +44,7 @@ /** * The slower (LIRS) cache. */ - private final CacheLIRS cache; + private final CacheLIRS cache; /** * Create a new string cache. @@ -49,7 +52,7 @@ * @param maxSize the maximum memory in bytes. */ StringCache(long maxSize) { - cache = CacheLIRS.newBuilder() + cache = CacheLIRS.newBuilder() .module("StringCache") .maximumWeight(maxSize) .averageWeight(100) @@ -76,15 +79,15 @@ if (s != null) { return s; } - StringCacheEntry key = new StringCacheEntry(hash, msb, lsb, offset, null); + StringCacheKey key = new StringCacheKey(hash, msb, lsb, offset); s = cache.getIfPresent(key); if (s == null) { s = loader.apply(offset); cache.put(key, s, getMemory(s)); } if (FastCache.isSmall(s)) { - key.setString(s); - fastCache.addString(hash, key); + fastCache.addString(hash, new FastCacheEntry(hash, msb, lsb, + offset, s)); } return s; } @@ -98,7 +101,7 @@ } private static int getMemory(String s) { - return 100 + s.length() * 2; + return estimateMemoryUsage(s) + 52; } private static int getEntryHash(long lsb, long msb, int offset) { @@ -125,7 +128,7 @@ /** * The cache array. */ - private final StringCacheEntry[] cache = new StringCacheEntry[CACHE_SIZE]; + private final FastCacheEntry[] cache = new FastCacheEntry[CACHE_SIZE]; /** * Get the string if it is stored. @@ -138,7 +141,7 @@ */ String getString(int hash, long msb, long lsb, int offset) { int index = hash & (CACHE_SIZE - 1); - StringCacheEntry e = cache[index]; + FastCacheEntry e = cache[index]; if (e != null && e.matches(msb, lsb, offset)) { return e.string; } @@ -159,36 +162,23 @@ return s.length() <= MAX_STRING_SIZE; } - void addString(int hash, StringCacheEntry entry) { + void addString(int hash, FastCacheEntry entry) { int index = hash & (CACHE_SIZE - 1); cache[index] = entry; } } - static class StringCacheEntry { + private static class StringCacheKey { private final int hash; private final long msb, lsb; private final int offset; - private String string; - StringCacheEntry(int hash, long msb, long lsb, int offset, String string) { + StringCacheKey(int hash, long msb, long lsb, int offset) { this.hash = hash; this.msb = msb; this.lsb = lsb; this.offset = offset; - this.string = string; - } - - void setString(String string) { - if (string == null) { - throw new NullPointerException(); - } - this.string = string; - } - - boolean matches(long msb, long lsb, int offset) { - return this.offset == offset && this.msb == msb && this.lsb == lsb; } @Override @@ -201,14 +191,14 @@ if (other == this) { return true; } - if (!(other instanceof StringCacheEntry)) { + if (!(other instanceof StringCacheKey)) { return false; } - StringCacheEntry o = (StringCacheEntry) other; + StringCacheKey o = (StringCacheKey) other; return o.hash == hash && o.msb == msb && o.lsb == lsb && o.offset == offset; } - + @Override public String toString() { StringBuilder buff = new StringBuilder(); @@ -220,4 +210,43 @@ } + private static class FastCacheEntry { + + private final int hash; + private final long msb, lsb; + private final int offset; + private final String string; + + FastCacheEntry(int hash, long msb, long lsb, int offset, String string) { + this.hash = hash; + this.msb = msb; + this.lsb = lsb; + this.offset = offset; + this.string = string; + } + + boolean matches(long msb, long lsb, int offset) { + return this.offset == offset && this.msb == msb && this.lsb == lsb; + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (!(other instanceof FastCacheEntry)) { + return false; + } + FastCacheEntry o = (FastCacheEntry) other; + return o.hash == hash && o.msb == msb && o.lsb == lsb && + o.offset == offset; + } + + } + } \ No newline at end of file