Improved server performance

This commit is contained in:
Eduard Urbach 2024-01-30 10:41:06 +01:00
parent b22d0b1367
commit 30c7d3d609
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
3 changed files with 78 additions and 8 deletions

View File

@ -15,7 +15,7 @@ func (ph *Router) Get(code byte, handler Handler) {
}
// handle deals with an incoming packet.
func (ph *Router) handle(p *Packet) {
func (ph *Router) handle(p Packet) {
defer func() {
if r := recover(); r != nil {
fmt.Println(p)

View File

@ -5,20 +5,26 @@ import (
"net"
)
const ChannelBufferSize = 4096
const (
// How many packets we will buffer in case our consumer can't keep up.
ChannelBufferSize = 4096
// The maximum data length of a UDP datagram (8 bytes UDP header, 20 bytes IP header).
UDPDataMaxLength = 65535 - 8 - 20
)
// Server represents a UDP server.
type Server struct {
handlers [256]Handler
socket *net.UDPConn
incoming chan *Packet
incoming chan Packet
packetCount int
}
// NewServer creates a new server.
func NewServer() *Server {
return &Server{
incoming: make(chan *Packet, ChannelBufferSize),
incoming: make(chan Packet, ChannelBufferSize),
}
}
@ -47,8 +53,10 @@ func (s *Server) ResetPacketCount() {
// Send sends the data prefixed with the byte code to the client.
func (s *Server) Send(code byte, data []byte, address *net.UDPAddr) error {
data = append([]byte{code}, data...)
_, err := s.socket.WriteToUDP(data, address)
tmp := make([]byte, len(data)+1)
tmp[0] = code
copy(tmp[1:], data)
_, err := s.socket.WriteToUDP(tmp, address)
return err
}
@ -71,7 +79,7 @@ func listen(port int) *net.UDPConn {
// read is a blocking call which will read incoming packets and handle them.
func (s *Server) read() {
buffer := make([]byte, 16384)
buffer := make([]byte, UDPDataMaxLength)
for {
n, addr, err := s.socket.ReadFromUDP(buffer)
@ -87,7 +95,7 @@ func (s *Server) read() {
tmp := make([]byte, n)
copy(tmp, buffer)
s.incoming <- &Packet{Data: tmp, Address: addr}
s.incoming <- Packet{Data: tmp, Address: addr}
s.packetCount++
}
}

View File

@ -0,0 +1,62 @@
package game_test
import (
"server/game"
"testing"
)
var (
code = byte(1)
data = []byte("Hello")
)
func BenchmarkSendAppend(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
tmp := append([]byte{code}, data...)
noop(tmp)
}
}
func BenchmarkSendCopy(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
tmp := make([]byte, len(data)+1)
tmp[0] = code
copy(tmp[1:], data)
noop(tmp)
}
}
func noop([]byte) {}
func BenchmarkReceivePointer(b *testing.B) {
b.ReportAllocs()
incoming := make(chan *game.Packet, 1)
for i := 0; i < b.N; i++ {
incoming <- &game.Packet{data, nil}
packet := <-incoming
if packet.Data[0] != 'H' {
b.FailNow()
}
}
}
func BenchmarkReceiveValue(b *testing.B) {
b.ReportAllocs()
incoming := make(chan game.Packet, 1)
data := []byte("Hello")
for i := 0; i < b.N; i++ {
incoming <- game.Packet{data, nil}
packet := <-incoming
if packet.Data[0] != 'H' {
b.FailNow()
}
}
}