Skip to content

Instantly share code, notes, and snippets.

@tevino
Last active January 20, 2024 22:50
Show Gist options
  • Save tevino/3a4f4ec4ea9d0ca66d4f to your computer and use it in GitHub Desktop.
Save tevino/3a4f4ec4ea9d0ca66d4f to your computer and use it in GitHub Desktop.
An example of using epoll in Go
package main
import (
"fmt"
"net"
"os"
"syscall"
)
const (
EPOLLET = 1 << 31
MaxEpollEvents = 32
)
func echo(fd int) {
defer syscall.Close(fd)
var buf [32 * 1024]byte
for {
nbytes, e := syscall.Read(fd, buf[:])
if nbytes > 0 {
fmt.Printf(">>> %s", buf)
syscall.Write(fd, buf[:nbytes])
fmt.Printf("<<< %s", buf)
}
if e != nil {
break
}
}
}
func main() {
var event syscall.EpollEvent
var events [MaxEpollEvents]syscall.EpollEvent
fd, err := syscall.Socket(syscall.AF_INET, syscall.O_NONBLOCK|syscall.SOCK_STREAM, 0)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer syscall.Close(fd)
if err = syscall.SetNonblock(fd, true); err != nil {
fmt.Println("setnonblock1: ", err)
os.Exit(1)
}
addr := syscall.SockaddrInet4{Port: 2000}
copy(addr.Addr[:], net.ParseIP("0.0.0.0").To4())
syscall.Bind(fd, &addr)
syscall.Listen(fd, 10)
epfd, e := syscall.EpollCreate1(0)
if e != nil {
fmt.Println("epoll_create1: ", e)
os.Exit(1)
}
defer syscall.Close(epfd)
event.Events = syscall.EPOLLIN
event.Fd = int32(fd)
if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil {
fmt.Println("epoll_ctl: ", e)
os.Exit(1)
}
for {
nevents, e := syscall.EpollWait(epfd, events[:], -1)
if e != nil {
fmt.Println("epoll_wait: ", e)
break
}
for ev := 0; ev < nevents; ev++ {
if int(events[ev].Fd) == fd {
connFd, _, err := syscall.Accept(fd)
if err != nil {
fmt.Println("accept: ", err)
continue
}
syscall.SetNonblock(fd, true)
event.Events = syscall.EPOLLIN | EPOLLET
event.Fd = int32(connFd)
if err := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, connFd, &event); err != nil {
fmt.Print("epoll_ctl: ", connFd, err)
os.Exit(1)
}
} else {
go echo(int(events[ev].Fd))
}
}
}
}
@lasselj
Copy link

lasselj commented Aug 9, 2021

If the compiler is a C compiler or a GO compiler what difference does it make? It is not the case that the binary produced by one is inherently "slower" than the other.

Yes, of course there's a huge difference.
GO compilers compiles your code to run inside a runtime, which is essentially an abstraction layer doing all the dirty work that C programmers manually do (memory management, process scheduling, and all of that).

But then again, this is the most important reason in my opinion:
epoll() is normally used because it provides a performance orders of magnitude bigger than a normal poll() or a select().
When you require very high performance, you don't want to ruin in because the garbage collector kicks in.

Go is not Java. Go code does not get compiled into platform independent byte code which is then "interpreted" at runtime "inside" anything. Narrowly as it relates to epoll you are wrong in your assessment that cgo is faster at performing a syscall operation, it just isn't. More broadly as it relates to the runtime libraries used by different languages you are also wrong. For fun, you could look up how in C main() gets called by the c runtime library or in C++ you could investigate what happens when someone calls new or free..... In any event, the fact that a language and its runtime library has memory allocation and garbage collection functionality does not infer that it is by definition "slower" than a language that doesn't. Similarly, a language that doesn't, does not have determinism built-in to its memory allocation allocation/deallocation system, which is - believe it or not - a part of its runtime library functions. Lastly, you are not wrong that there are instances where you could write something in C/C++ that would perform better than the equivalent written in Go. But as it relates to using cgo for epoll in this case you are wrong to assume that syscall() used in cgo is by definition faster than syscall.Syscall in go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment