Read the export test's heap only after pools drop their caches (closes #511)
check / check (push) Successful in 9m19s

TestArchiveExport_Streams read the heap after one collection. GORM's
table naming (through regexp) and encoding/json cache buffers in a
sync.Pool, which keeps them through one collection, so each reading
counted however many happened to be cached, and that swung between runs
by about the test's whole limit. It now collects twice before each
reading, the starting one included, so a reading is what the export
holds. No other test runs during the measurement: Go holds the parallel
tests until the sequential ones have finished.

Model: opus-5-5
This commit is contained in:
2026-10-06 07:26:55 +00:00
parent a9d77e20d7
commit 3a0495a787
@@ -460,8 +460,13 @@ func TestArchiveExport_OneFileOpenAtATime(t *testing.T) {
}
// heapPeak is an io.Writer that discards what it is given and records
// the largest heap it saw at a write. It collects garbage before each
// reading, so the heap it reads is what is still held.
// the largest heap it saw at a write. It collects garbage twice before
// each reading, so the heap it reads is what is still held. Once is not
// enough: the libraries the export calls (regexp, under GORM's table
// names, and encoding/json among them) cache buffers in a sync.Pool,
// which keeps them through one collection, so after one the reading
// counts however many happen to be cached. That varies from run to run
// by about as much as the limit in TestArchiveExport_Streams.
type heapPeak struct {
max uint64
}
@@ -469,6 +474,7 @@ type heapPeak struct {
func (p *heapPeak) Write(b []byte) (int, error) {
var m runtime.MemStats
runtime.GC()
runtime.GC()
runtime.ReadMemStats(&m)
p.max = max(p.max, m.HeapAlloc)
@@ -498,6 +504,8 @@ func exportHeapGrowth(t *testing.T, rows, bodySize int) uint64 {
export := listExport(t, path)
// Twice, for the reason heapPeak gives.
runtime.GC()
runtime.GC()
var start runtime.MemStats