Commit 57c9aa34 authored by David Fifield's avatar David Fifield
Browse files

Take ownership of buffer in QueuePacketConn.WriteTo.

Like the corresponding change to QueuePacketConn.QueueIncoming, this is
more efficient when the caller does not reuse the buffer.

Before:
	$ go test -bench=BenchmarkWriteTo -benchtime 2s -benchmem
	BenchmarkWriteTo-4       3777459               627 ns/op            1024 B/op          2 allocs/op
After:
	$ go test -bench=BenchmarkWriteTo -benchtime 2s -benchmem
	BenchmarkWriteTo-4       6702324               373 ns/op             512 B/op          1 allocs/op
parent d8183ff9
Loading
Loading
Loading
Loading
+5 −7
Original line number Diff line number Diff line
@@ -82,22 +82,20 @@ func (c *QueuePacketConn) ReadFrom(p []byte) (int, net.Addr, error) {
}

// WriteTo queues an outgoing packet for the given address. The queue can later
// be retrieved using the OutgoingQueue method.
// be retrieved using the OutgoingQueue method. This function takes ownership of
// p and the caller must not reuse it.
func (c *QueuePacketConn) WriteTo(p []byte, addr net.Addr) (int, error) {
	select {
	case <-c.closed:
		return 0, &net.OpError{Op: "write", Net: c.LocalAddr().Network(), Addr: c.LocalAddr(), Err: c.err.Load().(error)}
	default:
	}
	// Copy the slice so that the caller may reuse it.
	buf := make([]byte, len(p))
	copy(buf, p)
	select {
	case c.clients.SendQueue(addr) <- buf:
		return len(buf), nil
	case c.clients.SendQueue(addr) <- p:
		return len(p), nil
	default:
		// Drop the outgoing packet if the send queue is full.
		return len(buf), nil
		return len(p), nil
	}
}

+16 −0
Original line number Diff line number Diff line
@@ -25,3 +25,19 @@ func BenchmarkQueueIncoming(b *testing.B) {
	}
	b.StopTimer()
}

// BenchmarkWriteTo benchmarks the QueuePacketConn.WriteTo function.
func BenchmarkWriteTo(b *testing.B) {
	conn := NewQueuePacketConn(emptyAddr{}, 1*time.Hour)
	defer conn.Close()

	b.ResetTimer()
	s := 500
	for i := 0; i < b.N; i++ {
		// Use a variable for the length to stop the compiler from
		// optimizing out the allocation.
		p := make([]byte, s)
		conn.WriteTo(p, emptyAddr{})
	}
	b.StopTimer()
}