Improve pooling stats

This commit is contained in:
Clément Fournier
2020-04-20 08:07:04 +02:00
parent 1c4b241255
commit 7f65b1f910

View File

@ -5,9 +5,9 @@
package net.sourceforge.pmd.lang.ast.impl.javacc; package net.sourceforge.pmd.lang.ast.impl.javacc;
import java.util.HashMap;
import java.util.LongSummaryStatistics; import java.util.LongSummaryStatistics;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap;
import net.sourceforge.pmd.util.document.Chars; import net.sourceforge.pmd.util.document.Chars;
@ -19,12 +19,12 @@ import net.sourceforge.pmd.util.document.Chars;
*/ */
public final class StringPool { 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 boolean COLLECT_STATS = false;
private static final Stats stats = new Stats(); private static final Stats STATS = new Stats();
private static final String[] SINGLE_CHARS; private static final String[] SINGLE_CHARS;
static { static {
// all ascii characters // all ascii characters
SINGLE_CHARS = new String[128]; SINGLE_CHARS = new String[128];
@ -34,12 +34,15 @@ public final class StringPool {
} }
private final Map<Chars, String> pool = new HashMap<>(); private final Map<Chars, String> pool = new WeakHashMap<>();
String toString(CharSequence c, boolean doPool) { String toString(CharSequence c, boolean doPool) {
if (c.length() == 1) { if (c.length() == 1) {
char fst = c.charAt(0); char fst = c.charAt(0);
if (fst < 128) { if (fst < 128) {
if (COLLECT_STATS) {
STATS.addCacheHit(1);
}
return SINGLE_CHARS[fst]; return SINGLE_CHARS[fst];
} }
} }
@ -49,10 +52,10 @@ public final class StringPool {
return pool.compute((Chars) c, return pool.compute((Chars) c,
(chars, s) -> { (chars, s) -> {
if (s != null) { if (s != null) {
stats.addCacheHit(s.length()); STATS.addCacheHit(s.length());
return s; return s;
} else { } else {
stats.addCacheMiss(chars.length()); STATS.addCacheMiss(chars.length());
return chars.toString(); return chars.toString();
} }
}); });
@ -61,13 +64,15 @@ public final class StringPool {
} }
} }
if (COLLECT_STATS) { if (COLLECT_STATS) {
stats.addPass(c); STATS.addPass(c);
} }
return c.toString(); return c.toString();
} }
public static void printStats() { public static void printStats() {
stats.print(); if (COLLECT_STATS) {
STATS.print();
}
} }
private static class Stats { private static class Stats {
@ -84,15 +89,15 @@ public final class StringPool {
System.err.println("String pool stats"); System.err.println("String pool stats");
System.err.println("================="); System.err.println("=================");
System.err.println("Hits: " + hits + " (" + (hits * 100 / (total() + 1)) + "% of " + total() + ")"); System.err.println("Hits: " + hits + " (" + (hits * 100 / (total() + 1)) + "% of " + total() + ")");
System.err.println("Hit length (net savings): " + hitLen + " " + toSize(hitLen)); System.err.println("Hit length (net savings): " + hitLen + " (" + toSize(hitLen) + ")");
System.err.println( System.err.println("Total pool size: " + poolContents.getCount() + " strings (" + toSize(poolContents.getSum()) + ")");
"Total pool size: " + poolContents.getCount() + " strings (" + toSize(poolContents.getSum()) + ")");
System.err.println("Avg pooled string length: " + poolContents.getAverage() + " chars"); System.err.println("Avg pooled string length: " + poolContents.getAverage() + " chars");
System.err.println("Unpooled string length: " + notPooledAlloc + " chars (" + toSize(notPooledAlloc) + ")"); System.err.println("Unpooled string length: " + notPooledAlloc + " chars (" + toSize(notPooledAlloc) + ")");
} }
private String toSize(long charLen) { 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)) { if (charLen > (1 << 20)) {
return (charLen >> 20) + " MB"; return (charLen >> 20) + " MB";
} else if (charLen > (1 << 10)) { } else if (charLen > (1 << 10)) {