From 7f65b1f91047cea920c20bc5ee9e7f1cd2f887dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 20 Apr 2020 08:07:04 +0200 Subject: [PATCH] Improve pooling stats --- .../pmd/lang/ast/impl/javacc/StringPool.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/StringPool.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/StringPool.java index 7a0d1e464c..a8a238f473 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/StringPool.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/StringPool.java @@ -5,9 +5,9 @@ package net.sourceforge.pmd.lang.ast.impl.javacc; -import java.util.HashMap; import java.util.LongSummaryStatistics; import java.util.Map; +import java.util.WeakHashMap; import net.sourceforge.pmd.util.document.Chars; @@ -19,12 +19,12 @@ import net.sourceforge.pmd.util.document.Chars; */ public final class StringPool { + // This will be constant-folded by the JIT, use false in production private static final boolean COLLECT_STATS = false; - private static final Stats stats = new Stats(); + private static final Stats STATS = new Stats(); private static final String[] SINGLE_CHARS; - static { // all ascii characters SINGLE_CHARS = new String[128]; @@ -34,12 +34,15 @@ public final class StringPool { } - private final Map pool = new HashMap<>(); + private final Map pool = new WeakHashMap<>(); String toString(CharSequence c, boolean doPool) { if (c.length() == 1) { char fst = c.charAt(0); if (fst < 128) { + if (COLLECT_STATS) { + STATS.addCacheHit(1); + } return SINGLE_CHARS[fst]; } } @@ -49,10 +52,10 @@ public final class StringPool { return pool.compute((Chars) c, (chars, s) -> { if (s != null) { - stats.addCacheHit(s.length()); + STATS.addCacheHit(s.length()); return s; } else { - stats.addCacheMiss(chars.length()); + STATS.addCacheMiss(chars.length()); return chars.toString(); } }); @@ -61,13 +64,15 @@ public final class StringPool { } } if (COLLECT_STATS) { - stats.addPass(c); + STATS.addPass(c); } return c.toString(); } public static void printStats() { - stats.print(); + if (COLLECT_STATS) { + STATS.print(); + } } private static class Stats { @@ -84,15 +89,15 @@ public final class StringPool { System.err.println("String pool stats"); System.err.println("================="); System.err.println("Hits: " + hits + " (" + (hits * 100 / (total() + 1)) + "% of " + total() + ")"); - System.err.println("Hit length (net savings): " + hitLen + " " + toSize(hitLen)); - System.err.println( - "Total pool size: " + poolContents.getCount() + " strings (" + toSize(poolContents.getSum()) + ")"); + System.err.println("Hit length (net savings): " + hitLen + " (" + toSize(hitLen) + ")"); + System.err.println("Total pool size: " + poolContents.getCount() + " strings (" + toSize(poolContents.getSum()) + ")"); System.err.println("Avg pooled string length: " + poolContents.getAverage() + " chars"); System.err.println("Unpooled string length: " + notPooledAlloc + " chars (" + toSize(notPooledAlloc) + ")"); } private String toSize(long charLen) { - // assuming all pooled chars are latin-1, so 1B in a compressed string (byte[], not char[]) + // Assuming all pooled chars are latin-1, so 1B in a compressed string (byte[], not char[]) + // Before Java 9, it's twice as much if (charLen > (1 << 20)) { return (charLen >> 20) + " MB"; } else if (charLen > (1 << 10)) {