Yes, the Go runtime does use epoll internally and schedules gorountines when their data is available. See https://github.com/golang/go/blob/17b2fb1b656a275906b5071c562439d50a27f167/src/runtime/netpoll_epoll.go It does scale nicely and can handle tens of thousands or even hundreds of thousands of concurrent connections, without the "Thundering Herd" type behaviour which one would expect from such systems. I have not tried it with millions of connection, but if you are interested, then run a test, but the consume side of your test will run out of ports.
On Wednesday, 6 April 2022 at 14:43:16 UTC+1 Jack Li wrote: > Hi group, > > I am going through this page: https://studygolang.com/articles/22820 , It > claims that the 50 lines of Go code handles 1 million concurrent > connections from network clients, on 1 single server machine with a 4-Core > CPU and 16G memory. > > Does the package net already utilize IO Multiplexing internally, like > epoll (epoll_create, epoll_ctl, epoll_wait)? So I can just use package net > and gain the epoll ability automatically without calling epoll apis > manually in Go? > > Thanks > > Server: > ``` > package main > > import ( > "fmt" > "net" > "os" > "time" > ) > > var array []byte = make([]byte, 10) > > func checkError(err error, info string) (res bool) { > > if err != nil { > fmt.Println(info + " " + err.Error()) > return false > } > return true > } > > func Handler(conn net.Conn) { > for { > _, err := conn.Write(array) > if err != nil { > return > } > time.Sleep(10 * time.Second) > } > } > > func main() { > > for i := 0; i < 10; i += 1 { > array[i] = 'a' > } > > service := ":8888" > tcpAddr, _ := net.ResolveTCPAddr("tcp4", service) > l, _ := net.ListenTCP("tcp", tcpAddr) > > for { > conn, err := l.Accept() > if err != nil { > fmt.Printf("accept error, err=%s\n", err.Error()) > os.Exit(1) > } > go Handler(conn) > } > > } > ``` > > Client: > > ``` > package main > > import ( > "flag" > "fmt" > "net" > "os" > "time" > ) > > var RemoteAddr *string > var ConcurNum *int > var LocalAddr *string > > func init() { > RemoteAddr = flag.String("remote-ip", "127.0.0.1", "ip addr of remote > server") > ConcurNum = flag.Int("concurrent-num", 100, "concurrent number of > client") > LocalAddr = flag.String("local-ip", "0.0.0.0", "ip addr of remote > server") > } > > func consume() { > > laddr := &net.TCPAddr{IP: net.ParseIP(*LocalAddr)} > > var dialer net.Dialer > dialer.LocalAddr = laddr > > conn, err := dialer.Dial("tcp", *RemoteAddr+":8888") > if err != nil { > fmt.Println("dial failed:", err) > os.Exit(1) > } > defer conn.Close() > > buffer := make([]byte, 512) > > for { > _, err2 := conn.Read(buffer) > if err2 != nil { > fmt.Println("Read failed:", err2) > return > } > > // fmt.Println("count:", n, "msg:", string(buffer)) > > } > > } > > func main() { > flag.Parse() > for i := 0; i < *ConcurNum; i++ { > go consume() > } > time.Sleep(3600 * time.Second) > } > ``` > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/e139c771-4b11-49c6-9045-ed65c861ded2n%40googlegroups.com.