From dfb3bc1aa1208fe112fd665fc0f82c45be6c418c Mon Sep 17 00:00:00 2001 From: mayankpande88 Date: Sat, 19 Sep 2026 09:21:19 +0530 Subject: [PATCH] fix(go): take a heap snapshot, not a 30-second delta Every Go heap profile the collector produced could come back empty: Type: inuse_space Duration: 30.02s, Total samples = 0 Showing nodes accounting for 0, 0% of 0 total The URL was /debug/pprof/heap?seconds=30. On the heap endpoint the seconds parameter does not mean "sample for this long" - Go samples, waits, samples again and returns the DIFFERENCE. A service whose heap is steady across the window deltas to exactly zero, so the profile renders as an empty flamegraph and the pod's Profiler tab shows nothing. A heap profile is a snapshot of what the process is holding, so it takes no duration. Dropping seconds and adding gc=1 - which collects first, so the snapshot describes live memory rather than whatever the last GC left - turns the same request into a real profile. --- internal/agent/profiler/go_pprof.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/internal/agent/profiler/go_pprof.go b/internal/agent/profiler/go_pprof.go index 63a63fc..ff5d9b2 100644 --- a/internal/agent/profiler/go_pprof.go +++ b/internal/agent/profiler/go_pprof.go @@ -82,10 +82,17 @@ func (p *GoPprofProfiler) Invoke(job *job.ProfilingJob) (error, time.Duration) { func (p *goPprofManager) heapProfile(job *job.ProfilingJob, port string, fileName string) error { var out bytes.Buffer var stderr bytes.Buffer - targetURL := fmt.Sprintf( - "http://127.0.0.1:%s/debug/pprof/%s?seconds=%d", - port, "heap", int(job.Interval.Seconds()), - ) + // A heap profile is a snapshot of what the process is holding right now, so + // it takes no duration. Passing ?seconds= makes Go return a DELTA over that + // window instead — it samples, waits, samples again and subtracts — which + // nets to nothing whenever the heap is steady. That is how a 30s "heap + // profile" of a healthy service arrives as `Total samples = 0` with an + // empty flamegraph. + // + // ?gc=1 runs a collection first so the snapshot describes live memory + // rather than whatever the last GC cycle happened to leave behind; without + // it a process that has not GC'd yet reports nothing at all. + targetURL := fmt.Sprintf("http://127.0.0.1:%s/debug/pprof/heap?gc=1", port) // for local testing // cmd := exec.Command( // "curl", targetURL, "-o", fileName,