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

/**
 * Pembukuan alokasi model dengan penyadap sederhana: setiap penciptaan
 * objek dicatat per jenis, lalu tekanan GC dihitung dari matematika murni
 * (total byte / ukuran young gen) — tanpa statistik GC sungguhan.
 */
public class TekananAlokasi {

    // Pengganti profil alokasi: pencatat alokasi per jenis objek
    static final class Penyadap {
        long totalByte = 0;
        long totalObjek = 0;
        final Map<String, long[]> rincian = new LinkedHashMap<>(); // [objek, byte]

        void catat(String jenis, int ukuranPerObjek, int banyak) {
            totalObjek += banyak;
            totalByte += (long) ukuranPerObjek * banyak;
            long[] v = rincian.computeIfAbsent(jenis, k -> new long[2]);
            v[0] += banyak;
            v[1] += (long) ukuranPerObjek * banyak;
        }
    }

    public static void main(String[] args) {
        int pesanan = 2_000_000;
        long youngGen = 64L * 1024 * 1024; // model young gen 64 MB

        // Versi 1: tiap pesanan membuat objek baru — boxing, penggabungan
        // string, dan iterator loop-for di atas List<Integer>.
        Penyadap versi1 = new Penyadap();
        for (int i = 0; i < pesanan; i++) {
            versi1.catat("Integer (boxing)", 16, 1);
            versi1.catat("String (penggabungan)", 24, 2);
            versi1.catat("Iterator + lainnya", 40, 1);
        }

        // Versi 2: akumulator primitif + StringBuilder dipakai ulang.
        Penyadap versi2 = new Penyadap();

        System.out.println("== Rincian alokasi versi 1 ==");
        for (Map.Entry<String, long[]> e : versi1.rincian.entrySet()) {
            System.out.printf("  %-26s %,12d objek  %,13d byte%n",
                e.getKey(), e.getValue()[0], e.getValue()[1]);
        }
        System.out.printf("  %-26s %,12d objek  %,13d byte%n",
            "TOTAL", versi1.totalObjek, versi1.totalByte);
        System.out.println();
        System.out.println("== Rincian alokasi versi 2 ==");
        System.out.println("  nol alokasi per pesanan (akumulator int, StringBuilder dipakai ulang)");
        System.out.println();
        System.out.printf("Young gen model            = %,d byte%n", youngGen);
        System.out.printf("Estimasi minor GC versi 1  = %d kali%n", versi1.totalByte / youngGen);
        System.out.println("Estimasi minor GC versi 2  = 0 kali");
        System.out.println();
        System.out.println("Versi 2 bukan sekadar hemat:");
        System.out.println("tekanan alokasi = byte yang harus dipungut, bukan jumlah objek hidup");
    }
}
