Skip to content

Instantly share code, notes, and snippets.

@juanplopes
Last active November 27, 2019 15:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juanplopes/16f5245915db2b655721ba69fd740b05 to your computer and use it in GitHub Desktop.
Save juanplopes/16f5245915db2b655721ba69fd740b05 to your computer and use it in GitHub Desktop.
TestSizeUtils
import net.intelie.introspective.ObjectSizer;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
public class TestSizeUtils {
public static String formatBytes(double value) {
String[] NAMES = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
int name = 0;
while (Math.abs(value) >= 1024) {
value /= 1024;
name++;
}
return String.format(Locale.US,
name == 0 ? "%,.0f" : "%,.2f", value) + " " + NAMES[name];
}
public static String formattedSize(Object obj) {
return formatBytes(size(obj));
}
public static String formattedSizeNoStrings(Object obj) {
return formatBytes(sizeNoStrings(obj));
}
public static long size(Object obj) {
ObjectSizer sizer = new ObjectSizer();
sizer.resetTo(obj);
long total = 0;
long skipped = 0;
while (sizer.moveNext()) {
total += sizer.bytes();
if (WeakReference.class.isAssignableFrom(sizer.type()) || SoftReference.class.isAssignableFrom(sizer.type())) {
sizer.skipChildren();
skipped++;
}
}
assert sizer.skipped() == skipped;
return total;
}
public static long sizeNoStrings(Object obj) {
ObjectSizer sizer = new ObjectSizer();
sizer.resetTo(obj);
long total = 0;
while (sizer.moveNext()) {
if (!sizer.type().equals(String.class))
total += sizer.bytes();
}
assert sizer.skipped() == 0;
return total;
}
public static void dump(Object obj) {
ObjectSizer sizer = new ObjectSizer();
sizer.resetTo(obj);
Map<Class, AtomicLong> counts = new HashMap<>();
Map<Class, AtomicLong> total = new HashMap<>();
Map<UniqueWrapper, AtomicLong> doubleCount = new HashMap<>();
long skipped = 0;
long totalCount = 0, uniqueCount = 0, totalBytes = 0, uniqueBytes = 0;
while (sizer.moveNext()) {
totalCount++;
totalBytes += sizer.bytes();
counts.computeIfAbsent(sizer.type(), x -> new AtomicLong()).incrementAndGet();
total.computeIfAbsent(sizer.type(), x -> new AtomicLong()).addAndGet(sizer.bytes());
if (doubleCount.computeIfAbsent(new UniqueWrapper(sizer.current()), x -> new AtomicLong()).incrementAndGet() == 1) {
uniqueCount++;
uniqueBytes += sizer.bytes();
}
if (WeakReference.class.isAssignableFrom(sizer.type()) || SoftReference.class.isAssignableFrom(sizer.type())) {
sizer.skipChildren();
skipped++;
}
}
System.out.printf("total %10d %10s\n", totalCount, formatBytes(totalBytes));
System.out.printf("unique %10d %10s\n", uniqueCount, formatBytes(uniqueBytes));
System.out.printf("duplicate %10d %10s\n", (totalCount - uniqueCount), formatBytes(totalBytes - uniqueBytes));
System.out.println("histogram:");
total.entrySet().stream().sorted(Comparator.comparing(x -> -x.getValue().get())).forEach(entry -> {
System.out.printf(" %6d %10s %s\n", counts.get(entry.getKey()).get(), TestSizeUtils.formatBytes(entry.getValue().get()), entry.getKey().getCanonicalName());
});
assert sizer.skipped() == skipped;
sizer.clear();
System.out.println("top 10 duplicates: ");
doubleCount.entrySet().stream()
.filter(x -> x.getValue().get() > 1)
.sorted((Comparator.comparing(x -> -x.getValue().get())))
.limit(10)
.forEach(entry -> {
System.out.println(" " + entry.getKey().obj + " \t" + entry.getValue().get());
});
}
private static class UniqueWrapper {
private final Object obj;
public UniqueWrapper(Object obj) {
this.obj = obj;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof UniqueWrapper)) return false;
Object that = ((UniqueWrapper) o).obj;
if (that == null) return obj == null;
if (obj == that) return true;
Class<?> clazz = obj.getClass();
if (!clazz.isAssignableFrom(that.getClass())) return false;
if (byte[].class.equals(clazz))
return Arrays.equals((byte[]) obj, (byte[]) obj);
if (short[].class.equals(clazz))
return Arrays.equals((short[]) obj, (short[]) obj);
if (int[].class.equals(clazz))
return Arrays.equals((int[]) obj, (int[]) obj);
if (long[].class.equals(clazz))
return Arrays.equals((long[]) obj, (long[]) obj);
if (float[].class.equals(clazz))
return Arrays.equals((float[]) obj, (float[]) obj);
if (double[].class.equals(clazz))
return Arrays.equals((double[]) obj, (double[]) obj);
if (char[].class.equals(clazz))
return Arrays.equals((char[]) obj, (char[]) obj);
if (boolean[].class.equals(clazz))
return Arrays.equals((boolean[]) obj, (boolean[]) obj);
return Objects.equals(obj, that);
}
@Override
public int hashCode() {
Class<?> clazz = obj.getClass();
if (byte[].class.equals(clazz))
return Arrays.hashCode((byte[]) obj);
if (short[].class.equals(clazz))
return Arrays.hashCode((short[]) obj);
if (int[].class.equals(clazz))
return Arrays.hashCode((int[]) obj);
if (long[].class.equals(clazz))
return Arrays.hashCode((long[]) obj);
if (float[].class.equals(clazz))
return Arrays.hashCode((float[]) obj);
if (double[].class.equals(clazz))
return Arrays.hashCode((double[]) obj);
if (char[].class.equals(clazz))
return Arrays.hashCode((char[]) obj);
if (boolean[].class.equals(clazz))
return Arrays.hashCode((boolean[]) obj);
return Objects.hashCode(obj);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment