- errcheck: check type assertions from sync.Pool.Get() in
loadbalance/balancer.go and matcher/radix.go
- errcheck: check type assertion from list.Element.Value in
resolver/resolver.go evictLRULocked
- revive: add doc comment for exported ReleaseMatchResult function
SelectByKey and SelectExcludingByKey previously had a RLock→RUnlock→
rebuildCircle(Lock)→RLock pattern when the hash ring was empty. Under
cold-start concurrency, multiple goroutines could trigger simultaneous
rebuild attempts.
Add atomic.Bool 'rebuilt' flag with ensureRebuilt() check before any
RLock acquisition:
- Fast path: atomic load returns true → skip rebuild, proceed to RLock
- Cold start: first caller rebuilds and sets flag, subsequent callers
see the flag and skip rebuild
- Rebuild() explicitly resets the flag for explicit ring invalidation
Eliminates the RLock→Unlock→Lock→RLock transition entirely. The ring
is guaranteed ready before RLock is acquired.
filterHealthy() allocated 2 slices (available + backups) per call.
filterHealthyAndExclude() allocated 3 (adds excludeSet map).
IPHash allocated fnv.New64a() object per call.
All triggered on every request's LB selection.
Changes:
- Add filterContext struct holding reusable buffers, managed by sync.Pool
- Replace filterHealthy → filterInto (writes into pooled buffers)
- Replace filterHealthyAndExclude → filterIntoExcluding (pooled buffers)
- Add inline fnvHash64a() to avoid fnv.New64a() heap allocation
- Update all 6 balancer algorithms (RoundRobin, WeightedRoundRobin,
LeastConnections, IPHash, Random, ConsistentHash) to use pooled
filterContext via acquire/release pattern
- ConsistentHash.SelectExcludingByKey also uses pool for targetSet
- Remove buildExcludeSet (merged into filterIntoExcluding)
Result: allocs/op reduced from 2-3 to 0-1 on all LB Select paths.
FileInfoCache.Get previously acquired TWO locks on every cache hit:
1. RLock → check existence + TTL
2. Release RLock → Lock → MoveToFront (LRU update) → Unlock
The MoveToFront on every hit forced a read-to-write lock upgrade,
creating contention under concurrent reads.
Apply approximate LRU: skip MoveToFront on Get (read) path entirely.
LRU position is only updated in Set (write) path. This is the same
pattern already used by internal/cache/file_cache.go.
Result: Get fast path reduced from 2 lock acquisitions to 1 RLock.
TTL-expired entries still use double-check locking for safe removal.
DNS resolver LRU cache used []string slice for access ordering:
- moveToFrontLocked: O(n) linear scan + slice重组 per cache update
- storeCache held exclusive write lock during entire O(n) operation,
blocking all concurrent reads
Replace with container/list + map[string]*list.Element:
- storeCache: O(1) MoveToFront via list.Element pointer
- evictLRULocked: O(1) Back() + Remove()
- DeleteCacheEntry: O(1) instead of O(n) scan
This matches the LRU pattern already used by FileCache and
FileInfoCache. Write lock duration reduced from O(n) to O(1),
significantly reducing read contention under mixed workloads.
RadixTree.searchLongest previously allocated &MatchResult{} on the
heap every time it encountered a handler-bearing node during tree
traversal — potentially N allocations per lookup with only 1 surviving.
Changes:
- searchLongest now tracks best *RadixNode (stack pointer) instead of
allocating MatchResult at every handler node
- FindLongestPrefix allocates a single pooled MatchResult via sync.Pool
only when returning a match
- Add ReleaseMatchResult() for callers to return MatchResult to pool
- LocationEngine.Match releases pooled results after use
Result: 0 B/op, 0 allocs/op on tree traversal benchmarks (sequential
and parallel).
Remove sync.Mutex from Target's failure tracking hot path:
- failCount int64 → atomic.Int64
- failedUntil int64 → atomic.Int64
- IsAvailable(): Load() instead of Lock/Unlock, eliminating mutex
from every per-target check in every LB Select() call
- RecordFailure(): Add(1) + Store() instead of Lock/Unlock
- RecordSuccess(): Store(0) instead of Lock/Unlock
This removes the only mutex acquisition in the load balancing
selection path. Every Select() call iterates targets and calls
IsAvailable() on each — previously acquiring failMu per target
when MaxFails > 0. Now fully lock-free.
- Add comments for lua/api_log.go HTTP status codes and log levels
- Add comments for variable/builtin.go and ssl.go constants
- Add comments for utils/httperror.go error variables
- Add comments for matcher/matcher.go location types
- Add comments for compression/compression.go algorithms
- Include author attribution (xfy)
- proxyDebugLog: move Enabled() guard to call sites to avoid allocations
- proxyDebugLog: add default case for unsupported types
- static routes: remove unintended regex support to match original behavior