netpoll
Go's netpoll is a core I/O multiplexing mechanism implemented by the Go runtime. It enables Go to implement high-performance network services with a concise synchronous programming model (one Goroutine per connection). Its essence is the deep integration of operating system-level I/O multiplexing system calls (such as Linux's epoll) with Go's Goroutine scheduler.
Comparison between Netpoll and Native Go Net
1. Number of Goroutines
- Go Net: One connection per Goroutine.
- NetPoll: Multiple connections under one Goroutine.
2. Goroutine Context Switching/Scheduling Pressure
- Go Net: High switching pressure under high concurrency. Because Go Net has one connection per goroutine, frequent switching occurs when there are many goroutines.
- NetPoll: Low switching pressure under high concurrency. Because NetPoll shares one goroutine among multiple connections, there are fewer switches.
3. Memory Consumption
- Go Net: Memory consumption is positively correlated with the number of connections. High concurrency may cause memory pressure due to Goroutine explosion.
- NetPoll: Pre-allocates buffers and creates a buffer pool.
4. Trigger Mode
- Go Net: Uses Edge Triggered (ET). Reads all data at once, simple implementation.
- NetPoll: Uses Level Triggered (LT). No need to pre-allocate large memory as data buffers.
5. Support for Kernel and User Layer Sharing Buffer Pool (One Less Copy)
- Go Net: Not supported.
- NetPoll: Supported. Manages a Buffer pool directly handed to users, requiring one less copy.
6. Applicable Scenarios
- Go Net: Low concurrency, simple scenarios.
- NetPoll: High concurrency, low latency scenarios.
Netpoll Design Concepts
1. Basic Architecture
The native network library is developed based on epoll LT mode. The basic architecture is shown in the figure below:

2. Usage of Goroutines
There is a poll object pool. Each poll object has an epoll and is separately associated with a goroutine. The number of goroutines is consistent with the number of poll objects, and each poll object can listen to multiple file descriptors (fd).
3. I/O Read/Write Logic
- Each poll object starts a goroutine to continuously poll readable/writable events on the current epoll.
- Each epoll is associated with multiple fds, and each fd is associated with a Buffer.
- When a readable event is heard from an fd, data is read into the Buffer.
- Continuously poll and process data in the Buffer. When data reading is complete, notify the subsequent processing logic's goroutine pool GoPoll to execute.
- Interaction with the kernel through system calls is entirely controlled by netpoll. User-level reads and writes to Conn are just operating on the shared Buffer.
4. Advantages and Disadvantages
Advantages: Stronger support for high concurrency capabilities.
- Polling processes data in the Buffer, so there's no situation where data doesn't get processed.
- One goroutine corresponds to multiple connections. Even with many connections, the overhead of resource scheduling and switching is not significant.
- Supports user and kernel buffer sharing, reducing one data copy operation and improving efficiency.
Disadvantages: Requires more memory.
