perf: Configure yamux stream parameters and optimize I/O copy operations with 64KB buffer pooling.

cognitive-glitch committed Dec 9, 2025 at 13:23 UTC 2bbeccfdf28ea61c8a31b530c93b70e84542cf17
4 files changed +25 -6
cmd/portal-tunnel/main.go
+12 -2
@@ -17,6 +17,12 @@ import (
17 "gosuda.org/portal/utils"
18 )
19
20 +// bufferPool provides reusable 64KB buffers for io.CopyBuffer to eliminate
21 +// per-copy allocations and reduce GC pressure under high concurrency.
22 +var bufferPool = sync.Pool{
23 + New: func() any { return make([]byte, 64*1024) },
24 +}
25 +
26 var (
27 flagConfigPath string
28 flagRelayURLs string
@@ -174,12 +180,16 @@ func proxyConnection(ctx context.Context, localAddr string, relayConn net.Conn)
180 }()
181
182 go func() {
177 - _, err := io.Copy(localConn, relayConn)
183 + buf := bufferPool.Get().([]byte)
184 + _, err := io.CopyBuffer(localConn, relayConn, buf)
185 + bufferPool.Put(buf)
186 errCh <- err
187 }()
188
189 go func() {
182 - _, err := io.Copy(relayConn, localConn)
190 + buf := bufferPool.Get().([]byte)
191 + _, err := io.CopyBuffer(relayConn, localConn, buf)
192 + bufferPool.Put(buf)
193 errCh <- err
194 }()
195
cmd/relay-server/ratelimit/bucket.go
+2 -2
@@ -187,8 +187,8 @@ func (b *Bucket) Stats() (totalBytes, throttleHits int64, totalWaited time.Durat
187 time.Duration(atomic.LoadInt64(&b.totalWaited))
188 }
189
190 -// internal buffer pool for Copy - use smaller buffer for finer-grained rate limiting
191 -var bufPool = sync.Pool{New: func() any { return make([]byte, 16*1024) }}
190 +// internal buffer pool for Copy - 64KB reduces Take() call frequency and lock contention
191 +var bufPool = sync.Pool{New: func() any { return make([]byte, 64*1024) }}
192
193 // Copy copies from src to dst, enforcing the provided byte-rate bucket if not nil.
194 // Multiple Copy calls sharing the same bucket will fairly share the bandwidth.
portal/client.go
+4 -1
@@ -98,7 +98,10 @@ func NewRelayClient(conn io.ReadWriteCloser) *RelayClient {
98
99 // Create yamux session as client
100 config := yamux.DefaultConfig()
101 - config.Logger = nil // Disable logging for cleaner output
101 + config.Logger = nil // Disable logging for cleaner output
102 + config.MaxStreamWindowSize = 16 * 1024 * 1024 // 16MB for high-BDP scenarios
103 + config.StreamOpenTimeout = 75 * time.Second
104 + config.StreamCloseTimeout = 5 * time.Minute
105 sess, err := yamux.Client(conn, config)
106 if err != nil {
107 log.Error().Err(err).Msg("[RelayClient] Failed to create yamux session")
portal/relay.go
+7 -1
@@ -148,7 +148,13 @@ func NewRelayServer(credential *cryptoops.Credential, address []string) *RelaySe
148 }
149 }
150
151 -var _yamux_config = yamux.DefaultConfig()
151 +var _yamux_config = func() *yamux.Config {
152 + cfg := yamux.DefaultConfig()
153 + cfg.MaxStreamWindowSize = 16 * 1024 * 1024 // 16MB for high-BDP scenarios
154 + cfg.StreamOpenTimeout = 75 * time.Second
155 + cfg.StreamCloseTimeout = 5 * time.Minute
156 + return cfg
157 +}()
158
159 func (g *RelayServer) handleConn(id int64, connection *Connection) {
160 log.Debug().Int64("conn_id", id).Msg("[RelayServer] Handling new connection")