The Problem
Every rate-limited request triggers a full scan of all 4096 client entries to clean up expired ones β all while holding a mutex. π
This cleanup (prune()) doesn't need to happen on every request. It should run in a background goroutine every few minutes. Currently it serializes all rate-limited operations for no good reason.
Where to Look
beamsync/server.go β clientRateLimiter.allow() at line 110. The l.prune(now) call at line 120 is inside the lock.
clientRateLimiter.prune() at line 161 β the full map iteration.
- Move pruning to a background ticker goroutine.
The Goal
- Prune expired entries in a background goroutine, not on every request
- The
allow() method should be O(1) β just a map lookup and update
- Test: send requests from 1000 IPs and check lock hold time is sub-millisecond
The Problem
Every rate-limited request triggers a full scan of all 4096 client entries to clean up expired ones β all while holding a mutex. π
This cleanup (
prune()) doesn't need to happen on every request. It should run in a background goroutine every few minutes. Currently it serializes all rate-limited operations for no good reason.Where to Look
beamsync/server.goβclientRateLimiter.allow()at line 110. Thel.prune(now)call at line 120 is inside the lock.clientRateLimiter.prune()at line 161 β the full map iteration.The Goal
allow()method should be O(1) β just a map lookup and update