package main

import (
	"fmt"
	"os"
	"runtime"
	"runtime/pprof"
	"strings"
)

// buatLaporan membangun laporan transaksi sebagai satu string panjang.
func buatLaporan(jumlahBaris int) string {
	var b strings.Builder
	for i := range jumlahBaris {
		fmt.Fprintf(&b, "trx-%06d status=sukses jumlah=%d\n", i, 1000+i%7)
	}
	return b.String()
}

func main() {
	var awal, akhir runtime.MemStats
	runtime.ReadMemStats(&awal)

	laporan := buatLaporan(100_000)
	runtime.GC() // paksakan GC sebelum statistik akhir dibaca
	runtime.ReadMemStats(&akhir)

	berkasHeap, err := os.CreateTemp("", "heap-*.prof")
	if err != nil {
		fmt.Println("gagal membuat berkas profil heap:", err)
		return
	}
	if err := pprof.WriteHeapProfile(berkasHeap); err != nil {
		fmt.Println("gagal menulis profil heap:", err)
		return
	}
	berkasHeap.Close()

	berkasAllocs, err := os.CreateTemp("", "allocs-*.prof")
	if err != nil {
		fmt.Println("gagal membuat berkas profil allocs:", err)
		return
	}
	if err := pprof.Lookup("allocs").WriteTo(berkasAllocs, 0); err != nil {
		fmt.Println("gagal menulis profil allocs:", err)
		return
	}
	berkasAllocs.Close()

	// Nilai mentah TotalAlloc bergeser beberapa ratus byte antar eksekusi
	// karena alokasi internal runtime; pembulatan MiB dan ribuan menjadikan
	// output program ini stabil untuk dibandingkan.
	// Cuplikan menjaga isi laporan tetap hidup sehingga terlihat di profil heap.
	fmt.Println("panjang laporan:", len(laporan), "byte")
	fmt.Printf("cuplikan laporan: %q\n", laporan[:24])
	fmt.Println("TotalAlloc bertambah:", (akhir.TotalAlloc-awal.TotalAlloc)/1024/1024, "MiB")
	fmt.Println("Mallocs bertambah:", (akhir.Mallocs-awal.Mallocs)/1000, "ribu alokasi")
	fmt.Println("profil heap ditulis: true")
	fmt.Println("profil allocs ditulis: true")
}
