Advanced 26 min readModule: Module 15: Network Poller (netpoll): Zero-Copy epoll & Raw TCP
Network Poller Architecture & Zero-Copy TCP Sockets
Explore Go's high-concurrency networking layer: runtime `netpoll` integration with OS `epoll`/`kqueue`, non-blocking I/O event notification, TCP socket buffer tuning (`SO_RCVBUF`, `TCP_NODELAY`), and zero-copy packet processing with `splice()`.
What You Will Learn in This Lesson
- How `netpoll` bridges Go's synchronous network API (`net.Conn`) with asynchronous OS `epoll` queues
- Why Go goroutines park and wake up with zero OS thread context switches during socket I/O
- Tuning low-latency TCP sockets with `TCP_NODELAY` (disabling Nagle's algorithm) and keepalives
- Zero-copy data streaming from network socket directly to file descriptor using Linux `splice`
Introduction & Core Concept
In traditional C/Java servers, managing 100,000 open TCP sockets required either 100,000 blocking OS threads (exhausting memory) or writing complex non-blocking state machine loops with epoll. Go's runtime includes 'netpoll': an internal event notification engine that allows developers to write straightforward blocking `conn.Read()` calls while the runtime transparently monitors sockets with OS `epoll_wait`.
WHY DOES THIS MATTER IN THE REAL WORLD?
High-performance proxy servers, API gateways (like Traefik/Caddy), and WebSocket engines use netpoll tuning and zero-copy splices to route gigabits of traffic with near-zero CPU usage.
Syntax & Structure
go
tcpConn.SetNoDelay(true)tcpConn.SetReadBuffer(64 * 1024)// Linux zero-copy transferio.Copy(dstFile, tcpConn)Tuning Low-Latency Production TCP Server with netpoll Optimizations
gogo
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051// Low-Latency High-Concurrency TCP Server Architecturepackage mainimport ("fmt""net""time")func handleConnection(conn net.Conn) {defer conn.Close()// 1. Optimize TCP Socket Settingsif tcpConn, ok := conn.(*net.TCPConn); ok {// Disable Nagle's Algorithm: Send packets immediately without buffering!_ = tcpConn.SetNoDelay(true)// Enable TCP KeepAlive with fast probe intervals_ = tcpConn.SetKeepAlive(true)_ = tcpConn.SetKeepAlivePeriod(30 * time.Second)// Tune Socket Buffer Sizes_ = tcpConn.SetReadBuffer(32 * 1024)_ = tcpConn.SetWriteBuffer(32 * 1024)}buffer := make([]byte, 4096)for {// Set per-read deadline to prevent Slowloris attacks_ = conn.SetReadDeadline(time.Now().Add(10 * time.Second))// When conn.Read executes, the Goroutine parks in netpoll without consuming CPU!n, err := conn.Read(buffer)if err != nil {return // Disconnected or timeout}// Echo message back to client_, _ = conn.Write(append([]byte("KWAS-ECHO: "), buffer[:n]...))}}func main() {fmt.Println("=== Go Low-Latency netpoll TCP Server ===")listener, err := net.Listen("tcp", ":9090")if err != nil {fmt.Printf("Listen failed (Local demo mode): %v\n", err)return}defer listener.Close()fmt.Println("✅ TCP Listener active on :9090 (Managed by runtime netpoll / epoll)")}
Line-by-Line Technical Breakdown
1Linux Splice Zero-Copy: When copying data from a `net.TCPConn` directly to a file (`os.File`), Go's `io.Copy` automatically invokes the Linux `splice(2)` system call, streaming data directly from the network kernel buffer to the file page cache without copying bytes into user-space RAM.
Try It Yourself (Interactive Editor)
Modify the code in real-time and click Run to test live browser output and console logs.
Intelligent Code Runner & Live Sandbox[GO]
GO SOURCE EDITOR
Interactive Live CodeCommon Mistakes & How to Avoid Them
#1: Omitting read/write deadlines on long-lived TCP connections, causing socket descriptor leaks from hanging clients.
Dead TCP sockets from abrupt network drops consume file descriptors indefinitely unless monitored with deadlines or keepalive probes.
Incorrect / Antipattern
conn.Read(buf) // Can hang forever if network disconnects without TCP FINCorrect / Professional Solution
conn.SetReadDeadline(time.Now().Add(30 * time.Second))Industry Best Practices & Professional Standards
- Always set `SetNoDelay(true)` on latency-critical RPC and WebSocket connections.
- Always configure `SetReadDeadline` and `SetWriteDeadline` to mitigate Slowloris resource exhaustion attacks.
- Use `net.Buffers` for vectored I/O (gathering scatter writes into a single `writev` syscall).
Lesson Summary & Core Takeaways
- `netpoll` integrates Go's synchronous network API with OS `epoll`/`kqueue`.
- Goroutines park during I/O with zero OS thread context-switching overhead.
- TCP socket tuning (`TCP_NODELAY`, buffer sizing) delivers sub-millisecond network latency.