import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/** Profiler mini: penghitung panggilan per method menemukan hotspot beban kerja. */
public class ProfilHotspot {

    /** Satu baris laporan profil: nama method, jumlah panggilan, biaya per panggilan. */
    record BarisProfil(String method, long panggilan, int opPerPanggilan) {}

    /** Penghitung panggilan: peran instrumentasi profiler. */
    static long panggilValidasi;
    static long panggilHitungTotal;
    static long panggilSimpan;

    static void layaniRequest(int jumlahItem) {
        validasi();
        for (int i = 0; i < jumlahItem; i++) {
            hitungTotal(i);
        }
        simpan();
    }

    static void validasi() {
        panggilValidasi++;
    }

    static void hitungTotal(int item) {
        panggilHitungTotal++;
    }

    static void simpan() {
        panggilSimpan++;
    }

    public static void main(String[] args) {
        for (int r = 0; r < 1000; r++) {
            layaniRequest(3); // tiga item per request
        }

        List<BarisProfil> profil = new ArrayList<>(List.of(
                new BarisProfil("layaniRequest", 1000, 7),
                new BarisProfil("validasi", panggilValidasi, 20),
                new BarisProfil("hitungTotal", panggilHitungTotal, 50),
                new BarisProfil("simpan", panggilSimpan, 30)));
        profil.sort(Comparator.comparingLong((BarisProfil b) -> b.panggilan() * b.opPerPanggilan()).reversed());

        long totalOp = profil.stream().mapToLong(b -> b.panggilan() * b.opPerPanggilan()).sum();
        System.out.println("== Profil beban kerja: 1000 request x 3 item ==");
        System.out.printf("%-14s %10s %13s %10s %7s%n",
                "method", "panggilan", "op/panggilan", "total op", "porsi");
        for (BarisProfil b : profil) {
            long op = b.panggilan() * b.opPerPanggilan();
            System.out.printf("%-14s %10d %13d %10d %6.1f%%%n",
                    b.method(), b.panggilan(), b.opPerPanggilan(), op, 100.0 * op / totalOp);
        }
        System.out.printf("%-14s %10d %13s %10d %7s%n",
                "TOTAL", profil.stream().mapToLong(BarisProfil::panggilan).sum(), "-",
                totalOp, "100%");
    }
}
