import java.util.LinkedHashMap;
import java.util.Map;

/** Menghitung heap dari batas memori container dengan MaxRAMPercentage. */
public class HitungHeap {

    /** Komponen memori non-heap yang ikut memakan batas container (model tetap). */
    static final int METASPACE_MB = 64;
    static final int CODE_CACHE_MB = 48;
    static final int STACK_PER_THREAD_MB = 1;
    static final int DIRECT_BUFFER_MB = 32;
    static final int JUMLAH_THREAD = 30;

    static int heapMb(int limitMb, int persen) {
        return limitMb * persen / 100;
    }

    static void tabelPersentase() {
        System.out.println("== Heap maksimum dari MaxRAMPercentage ==");
        System.out.printf("%-14s %8s %8s %8s%n", "batas container", "25%", "50%", "75%");
        for (int limit : new int[]{256, 512, 1024}) {
            System.out.printf("%-14s %7dMB %7dMB %7dMB%n", limit + " MB",
                    heapMb(limit, 25), heapMb(limit, 50), heapMb(limit, 75));
        }
        System.out.println();
    }

    static void anggaran(String judul, int limitMb, int persenHeap) {
        Map<String, Integer> komponen = new LinkedHashMap<>();
        komponen.put("heap (" + persenHeap + "%)", heapMb(limitMb, persenHeap));
        komponen.put("metaspace", METASPACE_MB);
        komponen.put("code cache", CODE_CACHE_MB);
        komponen.put("thread stacks (" + JUMLAH_THREAD + " x " + STACK_PER_THREAD_MB + "MB)",
                JUMLAH_THREAD * STACK_PER_THREAD_MB);
        komponen.put("direct buffers", DIRECT_BUFFER_MB);

        int total = 0;
        System.out.println("== " + judul + " ==");
        for (var e : komponen.entrySet()) {
            total += e.getValue();
            System.out.printf("  %-38s : %5d MB%n", e.getKey(), e.getValue());
        }
        System.out.printf("  %-38s : %5d MB%n", "TOTAL", total);
        String verdict = (total > limitMb) ? "MELEBIHI batas -> risiko OOMKill" : "masih di dalam batas";
        System.out.println("  batas container " + limitMb + " MB -> " + verdict);
        System.out.println();
    }

    public static void main(String[] args) {
        tabelPersentase();
        anggaran("Anggaran 512 MB dengan heap 75%", 512, 75);
        anggaran("Anggaran 512 MB dengan heap 60%", 512, 60);
    }
}
