Author: sebb Date: Sat Jan 17 11:30:31 2015 New Revision: 1652582 URL: http://svn.apache.org/r1652582 Log: BCEL-186 Performance degradation with the UTF8 cache Tidy up and simplify caching code in case it can be made performant Might still be useful as a way of saving memory in some cases
Modified: commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/ConstantUtf8.java Modified: commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/ConstantUtf8.java URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/ConstantUtf8.java?rev=1652582&r1=1652581&r2=1652582&view=diff ============================================================================== --- commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/ConstantUtf8.java (original) +++ commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/ConstantUtf8.java Sat Jan 17 11:30:31 2015 @@ -40,53 +40,71 @@ public final class ConstantUtf8 extends private static final long serialVersionUID = -8709101585611518985L; private final String bytes; - private static final int MAX_CACHE_ENTRIES = 20000; - private static final int INITIAL_CACHE_CAPACITY = (int)(MAX_CACHE_ENTRIES/0.75); - private static HashMap<String, ConstantUtf8> cache; - private static int considered = 0; - private static int hits = 0; - private static int skipped = 0; - private static int created = 0; - static final boolean BCEL_STATISTICS = Boolean.getBoolean("bcel.statistics"); - static final boolean BCEL_DONT_CACHE = Boolean.getBoolean("bcel.dontCache"); + private static volatile int considered = 0; + private static volatile int hits = 0; + private static volatile int skipped = 0; + private static volatile int created = 0; + + // Set the size to 0 or below to skip caching entirely + private static final int MAX_CACHED_SIZE = Integer.getInteger("bcel.maxcached.size"); + private static final boolean BCEL_STATISTICS = Boolean.getBoolean("bcel.statistics"); + + + private static class CACHE_HOLDER { + + private static final int MAX_CACHE_ENTRIES = 20000; + private static final int INITIAL_CACHE_CAPACITY = (int)(MAX_CACHE_ENTRIES/0.75); + + private static final HashMap<String, ConstantUtf8> CACHE = + new LinkedHashMap<String, ConstantUtf8>(INITIAL_CACHE_CAPACITY, 0.75f, true) { + private static final long serialVersionUID = -8506975356158971766L; + + @Override + protected boolean removeEldestEntry(Map.Entry<String, ConstantUtf8> eldest) { + return size() > MAX_CACHE_ENTRIES; + } + }; + + } + + // for accesss by test code + static void printStats() { + System.err.println("Cache hit " + hits + "/" + considered +", " + skipped + " skipped"); + System.err.println("Total of " + created + " ConstantUtf8 objects created"); + } + + // for accesss by test code + static void clearStats() { + hits = considered = skipped = created = 0; + } static { if (BCEL_STATISTICS) { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { - System.err.println("Cache hit " + hits + "/" + considered +", " - + skipped + " skipped"); - System.err.println("Total of " + created + " ConstantUtf8 objects created"); + printStats(); } }); } } - public static synchronized ConstantUtf8 getCachedInstance(String s) { - if (BCEL_DONT_CACHE || s.length() > 200) { + public static ConstantUtf8 getCachedInstance(String s) { + if (s.length() > MAX_CACHED_SIZE) { skipped++; return new ConstantUtf8(s); } considered++; - if (cache == null) { - cache = new LinkedHashMap<String, ConstantUtf8>(INITIAL_CACHE_CAPACITY, 0.75f, true) { - private static final long serialVersionUID = -8506975356158971766L; - - @Override - protected boolean removeEldestEntry(Map.Entry<String, ConstantUtf8> eldest) { - return size() > MAX_CACHE_ENTRIES; + synchronized (ConstantUtf8.class) { // might be better with a specific lock object + ConstantUtf8 result = CACHE_HOLDER.CACHE.get(s); + if (result != null) { + hits++; + return result; } - }; + result = new ConstantUtf8(s); + CACHE_HOLDER.CACHE.put(s, result); + return result; } - ConstantUtf8 result = cache.get(s); - if (result != null) { - hits++; - return result; - } - result = new ConstantUtf8(s); - cache.put(s, result); - return result; } public static ConstantUtf8 getInstance(String s) {