From 7af91f7ef6aaec8b73c68ab13bfbc6f9d273d8c5 Mon Sep 17 00:00:00 2001 From: Kpa-clawbot Date: Sun, 12 Apr 2026 12:40:17 -0700 Subject: [PATCH] fix: perf page shows tracked memory instead of heap allocation (#718) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary The perf page "Memory Used" tile displayed `estimatedMB` (Go `runtime.HeapAlloc`), which includes all Go runtime allocations — not just packet store data. This made the displayed value misleading: it showed ~2.4GB heap when only ~833MB was actual tracked packet data. ## Changes ### Frontend (`public/perf.js`) - Primary tile now shows `trackedMB` as **"Tracked Memory"** — the self-accounted packet store memory - Added separate **"Heap (debug)"** tile showing `estimatedMB` for runtime visibility ### Backend - **`types.go`**: Added `TrackedMB` field to `HealthPacketStoreStats` struct - **`routes.go`**: Populate `TrackedMB` in `/health` endpoint response from `GetPerfStoreStatsTyped()` - **`routes_test.go`**: Assert `trackedMB` exists in health endpoint's `packetStore` - **`testdata/golden/shapes.json`**: Updated shape fixture with new field ### What was already correct - `/api/perf/stats` already exposed both `estimatedMB` and `trackedMB` - `trackedMemoryMB()` method already existed in store.go - Eviction logic already used `trackedBytes` (not HeapAlloc) ## Testing - All Go tests pass (`go test ./... -count=1`) - No frontend logic changes beyond template string field swap Fixes #717 Co-authored-by: you --- cmd/server/routes.go | 3 +++ cmd/server/routes_test.go | 3 +++ cmd/server/testdata/golden/shapes.json | 3 +++ cmd/server/types.go | 1 + public/perf.js | 3 ++- 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cmd/server/routes.go b/cmd/server/routes.go index e6833abf..7985622a 100644 --- a/cmd/server/routes.go +++ b/cmd/server/routes.go @@ -446,10 +446,12 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { // Real packet store stats pktCount := 0 var pktEstMB float64 + var pktTrackedMB float64 if s.store != nil { ps := s.store.GetPerfStoreStatsTyped() pktCount = ps.TotalLoaded pktEstMB = ps.EstimatedMB + pktTrackedMB = ps.TrackedMB } // Real cache stats @@ -515,6 +517,7 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { PacketStore: HealthPacketStoreStats{ Packets: pktCount, EstimatedMB: pktEstMB, + TrackedMB: pktTrackedMB, }, Perf: HealthPerfStats{ TotalRequests: int(perfRequests), diff --git a/cmd/server/routes_test.go b/cmd/server/routes_test.go index da9724dd..09d2108b 100644 --- a/cmd/server/routes_test.go +++ b/cmd/server/routes_test.go @@ -170,6 +170,9 @@ func TestHealthEndpoint(t *testing.T) { if _, ok := pktStore["estimatedMB"]; !ok { t.Error("expected estimatedMB in packetStore") } + if _, ok := pktStore["trackedMB"]; !ok { + t.Error("expected trackedMB in packetStore") + } // Verify eventLoop (GC pause metrics matching Node.js shape) el, ok := body["eventLoop"].(map[string]interface{}) diff --git a/cmd/server/testdata/golden/shapes.json b/cmd/server/testdata/golden/shapes.json index 518a159f..d715e89a 100644 --- a/cmd/server/testdata/golden/shapes.json +++ b/cmd/server/testdata/golden/shapes.json @@ -916,6 +916,9 @@ }, "estimatedMB": { "type": "number" + }, + "trackedMB": { + "type": "number" } } }, diff --git a/cmd/server/types.go b/cmd/server/types.go index 0b78ba63..7ac25c8c 100644 --- a/cmd/server/types.go +++ b/cmd/server/types.go @@ -115,6 +115,7 @@ type WebSocketStatsResp struct { type HealthPacketStoreStats struct { Packets int `json:"packets"` EstimatedMB float64 `json:"estimatedMB"` + TrackedMB float64 `json:"trackedMB"` } type SlowQuery struct { diff --git a/public/perf.js b/public/perf.js index 4a6fde69..379b6a0a 100644 --- a/public/perf.js +++ b/public/perf.js @@ -91,8 +91,9 @@ const ps = server.packetStore; html += `

In-Memory Packet Store

${ps.inMemory.toLocaleString()}
Packets in RAM
-
${ps.estimatedMB}MB
Memory Used
+
${ps.trackedMB}MB
Tracked Memory
${ps.maxMB}MB
Memory Limit
+
${ps.estimatedMB}MB
Heap (debug)
${ps.queries.toLocaleString()}
Queries Served
${ps.inserts.toLocaleString()}
Live Inserts
${ps.evicted.toLocaleString()}
Evicted