diff --git a/server/game/Router.go b/server/game/Router.go index 9fc944f..d28c209 100644 --- a/server/game/Router.go +++ b/server/game/Router.go @@ -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) diff --git a/server/game/Server.go b/server/game/Server.go index d606d48..cfc893c 100644 --- a/server/game/Server.go +++ b/server/game/Server.go @@ -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++ } } diff --git a/server/game/Server_test.go b/server/game/Server_test.go new file mode 100644 index 0000000..bc698c1 --- /dev/null +++ b/server/game/Server_test.go @@ -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() + } + } +}