mirror of
https://github.com/wweir/sower.git
synced 2026-10-19 16:14:33 +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
67 lines
1.9 KiB
Go
67 lines
1.9 KiB
Go
package router
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"testing"
|
|
)
|
|
|
|
// keepGlobal pins the trees across GC; without it the compiler may treat
|
|
// them as dead after the Match checks.
|
|
var keepGlobal struct {
|
|
block *RuleSet
|
|
direct *RuleSet
|
|
proxy *RuleSet
|
|
}
|
|
|
|
// TestRulesetMemoryFootprint builds rule shapes matching the production
|
|
// ad/china/gfw lists (synthetic, no external files) and reports the retained
|
|
// heap. Skipped under -short.
|
|
func TestRulesetMemoryFootprint(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("memory footprint test; skipped in -short mode")
|
|
}
|
|
t.Cleanup(func() {
|
|
keepGlobal = struct {
|
|
block *RuleSet
|
|
direct *RuleSet
|
|
proxy *RuleSet
|
|
}{}
|
|
})
|
|
|
|
// adlist-like: many exact domains under a few second-level domains.
|
|
block := make([]string, 0, 160000)
|
|
for i := 0; i < 160000; i++ {
|
|
block = append(block, fmt.Sprintf("ads%d.doubleclick.net", i))
|
|
}
|
|
// chinalist-like: many exact domains under many second-level domains.
|
|
direct := make([]string, 0, 110000)
|
|
for i := 0; i < 110000; i++ {
|
|
direct = append(direct, fmt.Sprintf("host%d.example%d.com", i, i%2000))
|
|
}
|
|
// gfwlist-like: wildcard-heavy.
|
|
proxy := make([]string, 0, 5000)
|
|
for i := 0; i < 5000; i++ {
|
|
proxy = append(proxy, fmt.Sprintf("**.site%d.com", i%100))
|
|
}
|
|
t.Logf("rules: block=%d direct=%d proxy=%d", len(block), len(direct), len(proxy))
|
|
|
|
keepGlobal.block = NewRuleSet(block...)
|
|
keepGlobal.direct = NewRuleSet(direct...)
|
|
keepGlobal.proxy = NewRuleSet(proxy...)
|
|
|
|
runtime.GC()
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
before := m.HeapAlloc
|
|
|
|
// Keep references live across GC.
|
|
if !keepGlobal.block.Match("ads1.doubleclick.net") || !keepGlobal.direct.Match("host1.example1.com") || !keepGlobal.proxy.Match("a.b.site1.com") {
|
|
t.Fatal("unexpected match result")
|
|
}
|
|
runtime.GC()
|
|
runtime.ReadMemStats(&m)
|
|
t.Logf("retained after GC: %d KiB (%.1f MB)", m.HeapAlloc/1024, float64(m.HeapAlloc)/1024/1024)
|
|
t.Logf("heap before/after: %d / %d", before, m.HeapAlloc)
|
|
}
|