How to Optimize Worker Thread Counts for High-Throughput Scenarios in MasterDnsVPN
Optimize MasterDnsVPN performance by aligning UDPReaders, DNSRequestWorkers, and DeferredSessionWorkers with your CPU core count and I/O patterns to maximize parallel packet processing.
MasterDnsVPN uses a multi-pool goroutine architecture to parallelize UDP packet ingestion, DNS resolution, and deferred SOCKS5 session handling. Tuning these worker thread counts is the primary mechanism for scaling the server to handle high-throughput scenarios such as thousands of simultaneous clients or extreme DNS query rates.
Understanding the Worker Pool Architecture
The server distributes work across four distinct configurable pools. Each pool feeds from specific channels and has hardcoded safety limits to prevent resource exhaustion.
UDP Readers (UDPReaders)
The UDPReaders configuration controls how many goroutines read raw packets from the net.UDPConn socket. These readers pull packets and push them onto a shared request channel for downstream processing.
- Default:
4 - Location:
internal/udpserver/server_runtime.goinfunc (s *Server) startUDPReaders - Best practice: Scale this to match or slightly exceed your physical CPU count when running on multi-core servers.
DNS Request Workers (DNSRequestWorkers)
DNSRequestWorkers consume items from the request channel and perform the actual resolution work, including cache lookups and upstream forwarding. They write responses directly back to the socket.
- Default:
8 - Location:
internal/udpserver/server_runtime.goinfunc (s *Server) startDNSWorkers - Key insight: These workers are CPU-intensive; blocking on upstream DNS latency means more workers can keep cores busy.
Deferred Session Workers (DeferredSessionWorkers)
When a SOCKS5 tunnel request encounters a slow or temporarily unavailable upstream, the deferred session processor queues the task. DeferredSessionWorkers handle this deferred establishment, each with its own bounded queue.
- Default:
4workers,4096queue limit (DeferredSessionQueueLimit) - Location:
internal/udpserver/deferred_session.goinnewDeferredSessionProcessor - Hard cap: The source code automatically clamps worker counts to a maximum of
64:
if workerCount > 64 {
workerCount = 64 // lines 84-85 of deferred_session.go
}
Client-Side Workers (ClientMaxRxTxWorkers)
On the client side, this setting limits parallel RX/TX workers for data streams.
- Default:
255 - Location:
internal/vpnproto/session_accept.go(encoded in the session-handshake payload) - Recommendation: Reduce to
8-16for laptops to prevent local CPU saturation.
Runtime Safety Limits and Validation
The server validates worker counts at startup to prevent misconfiguration. In internal/udpserver/deferred_session.go (lines 50-86), the newDeferredSessionProcessor function enforces:
if workerCount <= 0 {
workerCount = 1
}
if workerCount > 64 {
workerCount = 64
}
If you configure values outside these ranges, the server automatically clamps them and logs a warning via deferredSessionProcessor.maybeLogPressureLocked.
High-Throughput Configuration Strategies
Use the following targeted adjustments based on your hardware and traffic patterns:
- CPU-bound deployments (32+ cores): Increase
UDPReadersandDNSRequestWorkersto matchruntime.NumCPU()or slightly higher. A useful rule of thumb isworkers ≈ number_of_cores * 1.5. - I/O-bound scenarios (high upstream latency): Raise
DeferredSessionWorkerstoward the 64-worker cap and increaseDeferredSessionQueueLimitto8192or higher. This reduces wait time for pending SOCKS5 connections. - Memory-constrained environments: Keep
DeferredSessionQueueLimitmodest (e.g.,1024) and avoid excessiveDNSRequestWorkers. Each queue slot consumes memory, and thousands of pending jobs can cause OOM conditions. - Burst traffic patterns: Temporarily double
UDPReadersandDNSRequestWorkers. The deferred processor applies back-pressure whenworkerPending < 16 && sessionPending < p.sessionPendingCap, preventing memory spikes while absorbing peaks.
Implementing Configuration Changes
All worker counts are configurable via TOML or command-line flags through ServerConfigFlagBinder in internal/config/server.go (lines 108-112).
TOML configuration (server_config.toml):
UDP_READERS = 8
DNS_REQUEST_WORKERS = 16
DEFERRED_SESSION_WORKERS = 8
DEFERRED_SESSION_QUEUE_LIMIT = 8192
Command-line flags:
./masterdnsvpn-server -udp-readers=8 -dns-request-workers=16 -deferred-session-workers=8
Benchmarking Your Optimizations
Validate throughput changes using the built-in benchmark utility:
go run ./scripts/bench -udp-readers=8 -dns-workers=16
Adjust flags according to the benchmark's CLI options (see scripts/bench README) to measure QPS and latency improvements.
Summary
- MasterDnsVPN uses separate pools for UDP reading, DNS resolution, and deferred SOCKS5 sessions.
- Hard limits prevent runaway goroutine creation:
64max for deferred workers,255for client Rx/Tx. - Configuration happens via
internal/config/server.gousing TOML files or CLI flags. - Scaling rule: Set UDP and DNS workers to approximately
1.5xyour CPU core count for CPU-bound workloads. - I/O optimization: Increase deferred workers and queue limits when handling high-latency upstream connections.
Frequently Asked Questions
What are the default worker thread counts in MasterDnsVPN?
The server defaults to 4 UDPReaders, 8 DNSRequestWorkers, and 4 DeferredSessionWorkers with a queue limit of 4096. Client configurations default ClientMaxRxTxWorkers to 255.
Why is there a hard limit of 64 deferred session workers?
The limit prevents runaway goroutine creation under misconfiguration or attack conditions. Values exceeding 64 are automatically clamped to 64 in internal/udpserver/deferred_session.go lines 84-85.
How do I choose between increasing DNS workers versus deferred session workers?
Increase DNSRequestWorkers when your bottleneck is CPU processing or cache misses. Increase DeferredSessionWorkers when you observe delays in SOCKS5 tunnel establishment due to slow upstream I/O.
Can client-side worker counts impact server throughput?
Yes. The ClientMaxRxTxWorkers value (sent in the session handshake per internal/vpnproto/session_accept.go) determines how aggressively the client multiplexes streams. Over-provisioning this on low-powered clients can saturate local CPUs and reduce effective throughput without benefiting the server.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →