package com.oracle.svm.hosted.dashboard;
import com.oracle.svm.hosted.dashboard.ToJson.JsonObject;
import com.oracle.svm.hosted.dashboard.ToJson.JsonString;
import com.oracle.svm.hosted.dashboard.ToJson.JsonNumber;
import com.oracle.svm.hosted.dashboard.ToJson.JsonValue;
import com.oracle.svm.hosted.dashboard.ToJson.JsonArray;
import com.oracle.svm.hosted.FeatureImpl;
import com.oracle.svm.hosted.image.NativeImageHeap;
import org.graalvm.nativeimage.hosted.Feature;
import java.util.Arrays;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class HeapBreakdownJsonObject extends JsonObject {
private Feature.AfterHeapLayoutAccess access;
private boolean built = false;
private static final String INFO_NAME = "name";
private static final String INFO_SIZE = "size";
private static final String INFO_COUNT = "count";
private static final List<String> NAMES = Arrays.asList(INFO_NAME, INFO_SIZE, INFO_COUNT);
private final HashMap<String, Statistics> sizes = new HashMap<>();
HeapBreakdownJsonObject(Feature.AfterHeapLayoutAccess access) {
this.access = access;
}
Map<String, Long[]> getData() {
return sizes.entrySet().stream().collect(Collectors.toMap(Entry::getKey, (Entry<String, Statistics> e) -> new Long[]{e.getValue().size, e.getValue().count}));
}
@Override
Stream<String> getNames() {
return Arrays.asList("heap-size").stream();
}
@Override
JsonValue getValue(String name) {
return JsonArray.get(sizes.entrySet().stream().map(ClassJsonObject::new));
}
private static class ClassJsonObject extends JsonObject {
private final Map.Entry<String, Statistics> entry;
ClassJsonObject(Map.Entry<String, Statistics> entry) {
this.entry = entry;
}
@Override
Stream<String> getNames() {
return NAMES.stream();
}
@Override
JsonValue getValue(String name) {
switch (name) {
case INFO_NAME:
return JsonString.get(entry.getKey());
case INFO_SIZE:
return JsonNumber.get(entry.getValue().size);
case INFO_COUNT:
return JsonNumber.get(entry.getValue().count);
default:
return null;
}
}
}
private class Statistics {
long size = 0;
long count = 0;
}
@Override
protected void build() {
if (built) {
return;
}
FeatureImpl.AfterHeapLayoutAccessImpl config = (FeatureImpl.AfterHeapLayoutAccessImpl) access;
NativeImageHeap heap = config.getHeap();
for (NativeImageHeap.ObjectInfo info : heap.getObjects()) {
final String className = info.getClazz().getName();
Statistics stats = sizes.get(className);
if (stats == null) {
stats = new Statistics();
sizes.put(className, stats);
}
stats.size += info.getSize();
stats.count += 1;
}
access = null;
built = true;
}
}