perf(relay): remove global lock and optimize ban list lookup
- Remove duplicate connection tracking from bps_manager.go; RelayServer's event loop (cmdCheckAndIncLimit/cmdDecLimit) already handles this - Replace O(N×M) ban list iteration with O(1) map lookup in view.go - Delete isLeaseBanned function, add buildBannedMap for single-pass conversion
cognitive-glitch committed
Dec 9, 2025 at 12:55 UTC
e83d08610b1adab7f9c295a2f1f6bbcdaa24cbc8
2 files changed
+13
-40
cmd/relay-server/bps_manager.go
+3
-25
@@ -12,7 +12,7 @@ import (
12
// BPSManager manages per-lease bytes-per-second rate limiting
13
type BPSManager struct {
14
mu sync.Mutex
15
- bpsLimits map[string]int64 // leaseID -> bytes-per-second (0 = unlimited)
15
+ bpsLimits map[string]int64 // leaseID -> bytes-per-second (0 = unlimited)
16
bpsBuckets map[string]*ratelimit.Bucket // leaseID -> rate limit bucket
17
defaultBPS int64 // default bytes-per-second for new leases
18
}
@@ -116,40 +116,18 @@ func (m *BPSManager) Copy(dst io.Writer, src io.Reader, leaseID string) (int64,
116
return ratelimit.Copy(dst, src, bucket)
117
}
118
119
-// Connection tracking for relay (package level)
120
-var (
121
- relayedPerLeaseCount = make(map[string]int)
122
- relayLimitsLock sync.Mutex
123
-)
124
-
125
-// establishRelayWithBPS sets up bidirectional relay with BPS limiting
119
+// establishRelayWithBPS sets up bidirectional relay with BPS limiting.
120
+// Connection tracking is handled by RelayServer's event loop (cmdCheckAndIncLimit/cmdDecLimit).
121
func establishRelayWithBPS(clientStream, leaseStream *yamux.Stream, leaseID string, bpsManager *BPSManager) {
127
- // Register connection
128
- relayLimitsLock.Lock()
129
- relayedPerLeaseCount[leaseID]++
130
- connectionCount := relayedPerLeaseCount[leaseID]
131
- relayLimitsLock.Unlock()
132
-
133
- // Log relay start
122
bpsLimit := bpsManager.GetBPSLimit(leaseID)
123
log.Info().
124
Str("lease_id", leaseID).
125
Int64("bps_limit", bpsLimit).
138
- Int("active_connections", connectionCount).
126
Msg("[Relay] Starting relay connection")
127
141
- // Cleanup function
128
defer func() {
143
- relayLimitsLock.Lock()
144
- if relayedPerLeaseCount[leaseID] > 0 {
145
- relayedPerLeaseCount[leaseID]--
146
- }
147
- remainingCount := relayedPerLeaseCount[leaseID]
148
- relayLimitsLock.Unlock()
149
-
129
log.Info().
130
Str("lease_id", leaseID).
152
- Int("remaining_connections", remainingCount).
131
Msg("[Relay] Relay connection closed")
132
}()
133
cmd/relay-server/view.go
+10
-15
@@ -449,6 +449,9 @@ func convertLeaseEntriesToRows(serv *portal.RelayServer) []leaseRow {
449
rows := []leaseRow{}
450
now := time.Now()
451
452
+ // Build banned map once for O(1) lookup per lease
453
+ bannedMap := buildBannedMap(serv.GetLeaseManager().GetBannedLeases())
454
+
455
for _, leaseEntry := range leaseEntries {
456
// Check if lease is still valid
457
if now.After(leaseEntry.Expires) {
@@ -459,7 +462,7 @@ func convertLeaseEntriesToRows(serv *portal.RelayServer) []leaseRow {
462
identityID := string(lease.Identity.Id)
463
464
// Skip banned leases for user-facing list
462
- if isLeaseBanned(serv, identityID) {
465
+ if _, banned := bannedMap[identityID]; banned {
466
continue
467
}
468
@@ -574,21 +577,13 @@ func isLocalhost(r *http.Request) bool {
577
return host == "127.0.0.1" || host == "::1"
578
}
579
577
-// isLeaseBanned checks if a lease ID is in the banned list
578
-func isLeaseBanned(serv *portal.RelayServer, leaseID string) bool {
579
- bannedList := serv.GetLeaseManager().GetBannedLeases()
580
- for _, banned := range bannedList {
581
- bannedStr := string(banned)
582
- log.Debug().
583
- Str("checking_lease", leaseID).
584
- Str("banned_entry", bannedStr).
585
- Bool("match", bannedStr == leaseID).
586
- Msg("[BanCheck] Comparing lease IDs")
587
- if bannedStr == leaseID {
588
- return true
589
- }
580
+// buildBannedMap converts banned list to O(1) lookup map
581
+func buildBannedMap(bannedList [][]byte) map[string]struct{} {
582
+ m := make(map[string]struct{}, len(bannedList))
583
+ for _, b := range bannedList {
584
+ m[string(b)] = struct{}{}
585
}
591
- return false
586
+ return m
587
}
588
589
// AdminSettings stores persistent admin configuration