# Profiling dan Benchmarking Go 2026: pprof, trace, dan Pertanyaan Interview > Panduan lengkap profiling Go dengan pprof dan runtime/trace. Teknik analisis CPU, memori, dan goroutine untuk optimasi performa serta persiapan interview. - Published: 2026-09-19 - Updated: 2026-09-19 - Author: Anthony Fillion-Maillet - Reading time: 5 min --- Profiling Go dengan pprof dan package `runtime/trace` mengubah dugaan menjadi data konkret. Pertanyaan tentang performa muncul di hampir semua interview Go, dan kandidat yang mampu membaca flame graph atau menjelaskan kapan menggunakan `-inuse_space` versus `-allocs` akan menonjol. Tooling ini sudah tersedia di standard library, tidak memerlukan dependency eksternal, dan terintegrasi langsung dengan benchmark. > **Jenis Profile yang Perlu Diketahui** > > Go 1.24+ menyediakan tujuh profile bawaan: CPU, heap, allocs, goroutine, threadcreate, block, dan mutex. Go 1.26 menambahkan profile goroutine leak eksperimental yang mendeteksi goroutine terblokir yang tidak dapat dijangkau. ## CPU Profiling dengan pprof: Titik Awal CPU profiling mengambil sampel call stack pada interval reguler (default 100 Hz) dan mencatat fungsi mana yang mengkonsumsi waktu prosesor. Package `runtime/pprof` menangani pengumpulan level rendah, sementara `go tool pprof` menganalisis hasilnya. Profile selama 30 detik menangkap 3000 sampel, cukup untuk signifikansi statistik di sebagian besar aplikasi. Program standalone mengaktifkan profiling dengan memanggil `pprof.StartCPUProfile` saat startup. Profile ditulis ke file yang dibaca `go tool pprof` nanti: ```go // main.go package main import ( "flag" "log" "os" "runtime/pprof" ) var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") func main() { flag.Parse() if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { log.Fatal(err) } defer f.Close() pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } // Logika aplikasi di sini } ``` Untuk HTTP server, import `net/http/pprof` sebagai side effect. Package ini mendaftarkan handler di `/debug/pprof/` secara otomatis. Tidak perlu perubahan kode selain import: ```go // server.go package main import ( "net/http" _ "net/http/pprof" // Mendaftarkan handler /debug/pprof/* ) func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } ``` Ambil profile CPU 30 detik dari server yang berjalan dengan `go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30`. Tool ini mengunduh profile dan membuka shell interaktif. Parameter `seconds` mengontrol durasi pengumpulan. ## Menganalisis Profile: top, list, dan Flame Graph Shell pprof menyediakan perintah untuk mengidentifikasi bottleneck. `top` menampilkan fungsi yang mengkonsumsi CPU paling banyak, diurutkan berdasarkan flat time. Perintah `list` menampilkan source code dengan anotasi timing per baris, menunjukkan baris tepat yang mendominasi eksekusi. ```bash # Sesi terminal dengan go tool pprof $ go tool pprof cpu.prof (pprof) top 10 Showing nodes accounting for 4.2s, 85% of 4.9s total flat flat% sum% cum cum% 1.8s 36.73% 36.73% 1.8s 36.73% runtime.memmove 0.9s 18.37% 55.10% 0.9s 18.37% encoding/json.(*decodeState).scanWhile 0.5s 10.20% 65.30% 2.3s 46.94% main.processRecords ... (pprof) list processRecords Total: 4.9s 0.5s 2.3s (flat, cum) 46.94% of Total 20: for _, r := range records { 21: 0.3s 0.3s data := json.Marshal(r) 22: 0.2s 2.0s result := transform(data) ... ``` Antarmuka web menambahkan analisis visual. Jalankan `go tool pprof -http=:6060 cpu.prof` untuk membuka browser dengan flame graph, directed graph, dan source view. Sejak Go 1.26, flame graph muncul sebagai tampilan default di UI web. Flame graph menampilkan hierarki pemanggilan secara horizontal, dengan bar lebih lebar menunjukkan lebih banyak waktu yang dihabiskan di fungsi tersebut dan pemanggilnya. > **Membaca Flame Graph** > > Dalam flame graph, sumbu x merepresentasikan populasi sampel, bukan waktu. Setiap kotak adalah fungsi, dan lebarnya menunjukkan seberapa sering fungsi itu muncul dalam sampel. Fungsi parent berada di bawah children-nya. Cari plateau lebar di bagian atas: fungsi-fungsi itu melakukan pekerjaan sebenarnya. ## Memory Profiling: Heap vs Allocs Memory profiling menjawab dua pertanyaan berbeda. Profile **heap** (`-inuse_space`) menunjukkan apa yang menyimpan memori pada saat pengambilan. Profile **allocs** menunjukkan di mana alokasi terjadi sepanjang waktu, meskipun memori tersebut sudah dibebaskan. Untuk mengurangi penggunaan memori saat ini, periksa heap profile. Untuk mengurangi laju alokasi dan tekanan GC, periksa allocs profile. Laju alokasi tinggi memicu garbage collection yang sering, yang menghentikan goroutine dan meningkatkan penggunaan CPU. ```bash # Ambil heap profile dari server yang berjalan $ curl -o heap.prof http://localhost:8080/debug/pprof/heap $ go tool pprof -inuse_space heap.prof # Ambil allocs profile (jumlah alokasi selama 30 detik) $ curl -o allocs.prof "http://localhost:8080/debug/pprof/allocs?seconds=30" $ go tool pprof -alloc_objects allocs.prof ``` Flag `-inuse_objects` menghitung objek hidup daripada byte, berguna untuk mengidentifikasi fragmentasi memori. Flag `-alloc_space` menampilkan total byte yang dialokasikan selama periode profile, mengungkap fungsi yang mengolah memori meskipun melepaskannya dengan cepat. Hotspot alokasi umum termasuk konkatenasi string dalam loop (gunakan `strings.Builder`), konversi interface yang escape ke heap, dan pertumbuhan slice tanpa prealokasi. [Dokumentasi compiler Go](https://go.dev/doc/diagnostics#profiling) menjelaskan escape analysis secara detail. ## Benchmark Profiling dengan testing.B Package `testing` mengintegrasikan profiling langsung ke dalam benchmark. Kombinasi ini mengisolasi path kode spesifik tanpa noise dari aplikasi penuh. Benchmark profiling menjawab pertanyaan: "Bagaimana performa fungsi ini secara terisolasi?" ```go // parser_test.go package parser import "testing" func BenchmarkParseJSON(b *testing.B) { data := []byte(`{"id":1,"name":"test","values":[1,2,3]}`) b.ReportAllocs() // Sertakan statistik alokasi b.ResetTimer() // Kecualikan setup dari timing for i := 0; i < b.N; i++ { _, _ = Parse(data) } } ``` Generate profile selama eksekusi benchmark dengan flag. Flag `-cpuprofile` dan `-memprofile` menulis profile ke file untuk analisis nanti: ```bash # CPU profile selama benchmark $ go test -bench=BenchmarkParseJSON -cpuprofile=cpu.prof -benchtime=5s # Memory profile selama benchmark $ go test -bench=BenchmarkParseJSON -memprofile=mem.prof -benchtime=5s # Analisis hasilnya $ go tool pprof -http=:6060 cpu.prof ``` Flag `-benchtime` mengontrol berapa lama benchmark berjalan. Run yang lebih lama menghasilkan profile yang lebih akurat tetapi membutuhkan lebih banyak waktu. Run 5 detik biasanya memberikan hasil yang stabil. Untuk micro-benchmark, gunakan `-count=10` untuk menjalankan beberapa iterasi dan memeriksa varians. ## Execution Tracing dengan runtime/trace Sementara pprof menunjukkan di mana waktu dihabiskan, `runtime/trace` menunjukkan kapan event terjadi. Trace menangkap penjadwalan goroutine, system call, event GC, dan aktivitas jaringan pada timeline. Visibilitas ke dalam perilaku concurrency ini melengkapi profiling statistik. ```go // trace_example.go package main import ( "os" "runtime/trace" ) func main() { f, _ := os.Create("trace.out") defer f.Close() trace.Start(f) defer trace.Stop() // Logika aplikasi runConcurrentTasks() } ``` Trace viewer menampilkan lifetime goroutine, event blocking, dan utilisasi prosesor. Setiap goroutine muncul sebagai bar horizontal, dengan warna yang menunjukkan apakah ia berjalan, terblokir, atau menunggu penjadwalan: ```bash $ go tool trace trace.out # Membuka browser di http://127.0.0.1:port ``` Untuk HTTP server, ambil trace dari `/debug/pprof/trace?seconds=5`. Trace viewer menunjukkan goroutine mana yang terblokir pada apa, mengungkap pola contention yang tidak terlihat oleh CPU profile. View "Goroutine analysis" mengelompokkan goroutine berdasarkan situs pembuatan, membantu mengidentifikasi leak atau fan-out yang tidak terduga. Trace lebih berat dari profile. Trace 5 detik dari server yang sibuk dapat menghasilkan ratusan megabyte data. Gunakan durasi pendek dan pengumpulan yang ditargetkan. [Blog Go tentang execution tracing](https://go.dev/blog/execution-traces-2024) membahas teknik analisis lanjutan. ## Block dan Mutex Profiling untuk Contention Block profiling mencatat goroutine yang menunggu pada synchronization primitive: channel, mutex, dan condition variable. Mutex profiling fokus khusus pada mutex contention. Profile ini mengungkap bottleneck concurrency yang tidak terlihat oleh CPU profiling. Aktifkan profile ini dengan mengatur parameter runtime sebelum contention terjadi: ```go // Aktifkan block profiling (1 = sampel semua event blocking) runtime.SetBlockProfileRate(1) // Aktifkan mutex profiling (1 = sampel semua mutex contention) runtime.SetMutexProfileFraction(1) ``` Untuk produksi, atur nilai lebih tinggi untuk mengurangi overhead. Block profile rate 1000000 (satu mikrodetik) atau mutex fraction 100 memberikan data yang berguna dengan dampak minimal. Mengatur nilai ini terlalu rendah menangkap setiap event dan dapat memperlambat aplikasi. Ambil profile ini dari endpoint standar: ```bash $ curl -o block.prof http://localhost:8080/debug/pprof/block $ curl -o mutex.prof http://localhost:8080/debug/pprof/mutex $ go tool pprof block.prof ``` Block profile menunjukkan total waktu menunggu, bukan jumlah event blocking. Fungsi yang memblokir selama 1 detik sekali terlihat identik dengan yang memblokir selama 1 milidetik 1000 kali. Gunakan execution tracing untuk membedakan kasus-kasus ini. ## Kesalahan Umum dalam Profiling Profiling memperkenalkan overhead yang dapat mempengaruhi hasil. CPU profiling menambah sekitar 5% overhead. Memory profiling mengambil sampel alokasi (1 per 512KB secara default), sehingga alokasi kecil mungkin tidak muncul. Tracing menangkap setiap event dan dapat menambah 10-30% overhead. Beberapa kesalahan menyebabkan profile yang menyesatkan: **Profiling build yang dioptimasi secara berbeda.** Selalu profile dengan flag build yang sama dengan yang digunakan di produksi. Debug build menonaktifkan inlining dan optimasi, membuat hot spot muncul di tempat berbeda. **Profiling di bawah load buatan.** Profile dari server idle menunjukkan idle loop, bukan bottleneck sebenarnya. Profile di bawah pola traffic realistis. **Mengabaikan overhead GC.** CPU profile mencakup waktu yang dihabiskan dalam garbage collection. Kehadiran `runtime.gc*` yang tinggi menunjukkan masalah alokasi memori, bukan masalah CPU. Atasi dengan memory profiling. **Durasi profiling yang pendek.** Profile 1 detik hanya menangkap 100 sampel. Noise statistik mendominasi. Profile setidaknya 30 detik di bawah load stabil. ## Pertanyaan Interview Go tentang Profiling Pertanyaan performa menguji apakah kandidat dapat mendiagnosis masalah nyata. Interviewer mencari keakraban dengan tooling dan pemahaman tentang apa yang diungkapkan setiap profile. **T: Kapan heap profiling menunjukkan hasil berbeda dari allocs profiling?** Heap menunjukkan memori yang tertahan pada saat pengambilan. Allocs menunjukkan semua alokasi, termasuk memori yang dibebaskan. Fungsi yang mengalokasikan buffer temporer dalam loop muncul di allocs tetapi tidak di heap jika buffer dikumpulkan sebelum snapshot. Gunakan allocs untuk mengurangi tekanan GC, heap untuk menemukan leak. **T: Sebuah goroutine tampak stuck. Profile mana yang membantu?** Goroutine profile menunjukkan stack trace semua goroutine. Block profile menunjukkan di mana goroutine menunggu. Untuk Go 1.26+, profile goroutine leak eksperimental mendeteksi goroutine yang tidak dapat dijangkau yang terblokir pada channel atau mutex. Execution tracing menunjukkan timeline event blocking. **T: Apa arti flat percentage versus cumulative percentage di pprof?** Flat mengukur waktu di fungsi itu sendiri. Cumulative mencakup waktu di fungsi yang dipanggilnya. Fungsi dengan cumulative tinggi tetapi flat rendah adalah koordinator yang mendelegasikan pekerjaan. Fungsi dengan flat time tinggi melakukan komputasi sebenarnya. Optimalkan fungsi dengan flat time tinggi terlebih dahulu. **T: Bagaimana cara profiling benchmark tanpa memprofiling setup tes?** Panggil `b.ResetTimer()` setelah setup selesai. Untuk benchmark dengan setup per-iterasi, gunakan `b.StopTimer()` dan `b.StartTimer()` di sekitar kode setup. Panggilan timer memiliki overhead nanodetik, jadi hindari di loop ketat. **T: Mengapa fungsi mungkin tidak muncul di CPU profile meskipun lambat?** CPU profiling hanya menangkap fungsi yang aktif menggunakan CPU. Fungsi I/O-bound (menunggu jaringan, disk, atau channel) muncul di block profile atau trace, bukan CPU profile. Sampling juga dapat melewatkan fungsi yang berjalan total kurang dari 10ms. **T: Bagaimana implementasi Swiss Tables map Go 1.24 mempengaruhi profiling?** Go 1.24 mengganti map berbasis bucket dengan Swiss Tables, mengurangi overhead CPU sebesar 2-3% untuk workload berat map. Profile yang diambil sebelum dan sesudah upgrade menunjukkan call stack terkait map yang berbeda. Flag `GOEXPERIMENT=noswissmap` mengembalikan ke implementasi lama untuk perbandingan. ## Continuous Profiling di Produksi Profile point-in-time melewatkan masalah transien. Tool continuous profiling seperti [Pyroscope](https://pyroscope.io/) atau [Parca](https://www.parca.dev/) mengumpulkan sampel low-overhead secara terus menerus, memungkinkan perbandingan antar deployment. Tool ini mengkorelasikan profile dengan metrik dan trace. Profile bawaan Go bekerja dengan tool ini melalui format pprof. Layanan [pprof.me](https://pprof.me/) menambahkan fitur perbandingan di 2026, memungkinkan upload dan diff profile untuk mengkuantifikasi dampak optimasi sebelum dan sesudah perubahan kode. Untuk [persiapan interview Go](/technologies/go/interview-questions/testing), memahami baik tooling maupun konsep dasarnya sangat penting. [Package context](/technologies/go/interview-questions/context-package) dan [pola concurrency](/technologies/go/interview-questions/concurrency-patterns) sering muncul bersamaan dengan pertanyaan profiling. Optimasi performa seringkali memerlukan penggabungan data profiling dengan pengetahuan tentang perilaku runtime Go. ## Apa yang Diungkapkan Go Profiling tentang Perilaku Aplikasi - CPU profile mengidentifikasi fungsi hot tetapi melewatkan pekerjaan I/O-bound. Kombinasikan dengan trace untuk gambaran lengkap. - Memory profile membedakan masalah retensi (heap) dari churn alokasi (allocs). Gunakan `-inuse_space` untuk leak, `-alloc_space` untuk tekanan GC. - Block dan mutex profile mengekspos contention yang tidak dapat dilihat CPU profile. Aktifkan ketika latency melonjak di bawah load. - Benchmark profiling mengisolasi path kode spesifik. Selalu panggil `b.ReportAllocs()` dan `b.ResetTimer()` untuk pengukuran akurat. - Trace viewer menunjukkan penjadwalan goroutine dan event blocking pada timeline, esensial untuk mendiagnosis bug concurrency. - Peningkatan runtime Go 1.24 mengurangi overhead CPU sebesar 2-3% melalui Swiss Tables map dan implementasi mutex baru. - Profiling produksi dengan endpoint `/debug/pprof/` memerlukan autentikasi. Jangan pernah ekspos endpoint ini secara publik: mereka membocorkan state aplikasi internal dan dapat memungkinkan denial-of-service melalui pengumpulan profile yang mahal. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/id/blog/go/go-profiling-benchmarking-pprof-trace-interview