sclass InvestigateNonTransientGraph { MetaTransformer mt; Map back = identityHashMap(); new MultiSet objectsBySize; new MultiMap objectsByClass; new MultiSet objectsByDynClass; *() { mt = metaTransformer_collectionAndMap(); mt.add(new MTSH_nonTransientFields); mt.avoidCycles(); mt.markPointer = (a, b) -> { putIfNotThere(back, b, a); }; } void scan(O root) { VStack.Computable v = mt.new visit_vstackComputable(o -> { objectsBySize.add(o.getClass(), clampToInt(unsafe_sizeOf(o))); objectsByClass.put(o.getClass(), o); if (o instanceof DynamicObject) objectsByDynClass.add(shortDynClassName(o)); }, root); vstackCompute(v); } void printResults() { print("Seen objects: " + n2(mt.seen)); print(); print("Most popular classes:"); print(multiSetToLines(multiMapToMultiSet(objectsByClass), 20)); print(); print("Total bytes per class:"); print(multiSetToLines(objectsBySize, 20)); if (!empty(objectsByDynClass)) { print("Popular dynamic classes:"); print(multiSetToLines(objectsByDynClass, 20)); } } L biggestOfClass(Class c) { ret sortedByCalculatedFieldDesc unsafe_objectSize((Cl) objectsByClass.get(c)); } void printBiggestByteArrays() { for (var array : takeFirst(2, biggestOfClass(byteArrayType()))) { print("Byte array " + n2_l(array)); O o = array; repeat 10 { if (o == null) break; o = back.get(o); print(" <= " + className/*shortenedToStringWithClass*/(o)); } } } }