mirror of
https://github.com/wweir/sower.git
synced 2026-10-20 20:04:32 +00:00
- countingConn batches per-domain attribution (32KiB/500ms) so the relay hot path pays two atomics per I/O instead of a global mutex; Close drains - Precompute OTel byte attributes to drop per-I/O allocations - suffixtree: indexMap only for nodes with >=8 children; Match stays read-only for concurrent queries - Soft Go memory limit (128MiB default, GOMEMLIMIT/SOWER_MEMORY_LIMIT_MB override) cuts resident memory from ~240MB to ~130MB on the default ad/china/gfw rule sets - Split stats.go into snapshot/eviction/counting by responsibility
45 lines
1.2 KiB
Go
45 lines
1.2 KiB
Go
package admin
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"testing"
|
|
)
|
|
|
|
// TestStatsMemoryFootprint measures the heap retained by the domain table at
|
|
// realistic and worst-case cardinalities. Run with -count=1.
|
|
func TestStatsMemoryFootprint(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("memory footprint test; skipped in -short mode")
|
|
}
|
|
for _, domains := range []int{10_000, 50_000, 100_000} {
|
|
s := newTestStats(t)
|
|
for i := 0; i < domains; i++ {
|
|
domain := fmt.Sprintf("host%d.example.com", i)
|
|
s.record(domain, SourceHTTPS, "192.168.1.10", 1, 1000, 2000, func(d *domainStat, src *sourceStat, dc *clientStat) {
|
|
d.conns++
|
|
d.bytesUp += 1000
|
|
d.bytesDown += 2000
|
|
src.bytesUp += 1000
|
|
src.bytesDown += 2000
|
|
if dc != nil {
|
|
dc.bytesUp += 1000
|
|
dc.bytesDown += 2000
|
|
}
|
|
})
|
|
}
|
|
|
|
runtime.GC()
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
s.mu.Lock()
|
|
retained := len(s.domains)
|
|
s.mu.Unlock()
|
|
t.Logf("%d records: retained=%d heap=%d KiB (%.0f B/domain)",
|
|
domains, retained, m.HeapAlloc/1024, float64(m.HeapAlloc)/float64(max(retained, 1)))
|
|
if retained != domains {
|
|
t.Errorf("expected %d retained domains, got %d", domains, retained)
|
|
}
|
|
}
|
|
}
|