]> Cypherpunks repositories - gostls13.git/commitdiff
net: optimize WriteToUDPAddrPort
authorJosh Bleecher Snyder <josharian@gmail.com>
Mon, 1 Nov 2021 20:23:39 +0000 (13:23 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 2 Nov 2021 18:35:29 +0000 (18:35 +0000)
See the recent change optimizing WriteMsgUDPAddrPort
for an explanation of why this change includes copy/paste/modify
instead of implementing WriteToUDP using WriteToUDPAddrPort.

name                          old time/op    new time/op    delta
WriteToReadFromUDPAddrPort-8    5.02µs ± 3%    4.71µs ± 2%   -6.31%  (p=0.000 n=15+14)

name                          old alloc/op   new alloc/op   delta
WriteToReadFromUDPAddrPort-8     68.0B ± 0%      4.0B ± 0%  -94.12%  (p=0.000 n=15+15)

name                          old allocs/op  new allocs/op  delta
WriteToReadFromUDPAddrPort-8      3.00 ± 0%      1.00 ± 0%  -66.67%  (p=0.000 n=15+15)

Change-Id: I301715e774de07eb6ccb4e329ccf2e554609abc1
Reviewed-on: https://go-review.googlesource.com/c/go/+/360599
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/net/udpsock.go
src/net/udpsock_plan9.go
src/net/udpsock_posix.go

index 0d563fd4f5c1e8595a164e73f18a21553756786b..a829789a1bc97a4d22779904612738dd840fe4e0 100644 (file)
@@ -207,11 +207,14 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
 
 // WriteToUDPAddrPort acts like WriteTo but takes a netip.AddrPort.
 func (c *UDPConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) {
-       // TODO(bradfitz): make this efficient, making the internal net package
-       // type throughout be netip.Addr and only converting to the net.IP slice
-       // version at the edge. But for now (2021-10-20), this is a wrapper around
-       // the old way.
-       return c.WriteToUDP(b, UDPAddrFromAddrPort(addr))
+       if !c.ok() {
+               return 0, syscall.EINVAL
+       }
+       n, err := c.writeToAddrPort(b, addr)
+       if err != nil {
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addrPortUDPAddr{addr}, Err: err}
+       }
+       return n, err
 }
 
 // WriteTo implements the PacketConn WriteTo method.
index ac5afa22810006aef6bfbc14c92a17a290b25dcf..dfb81a8d0c4742029c1e08eab5215079162210d7 100644 (file)
@@ -53,6 +53,10 @@ func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) {
        return len(b), nil
 }
 
+func (c *UDPConn) writeToAddrPort(b []byte, addr netip.AddrPort) (int, error) {
+       return c.writeTo(b, UDPAddrFromAddrPort(addr)) // TODO: optimize instead of allocating
+}
+
 func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
        return 0, 0, syscall.EPLAN9
 }
index 646687d148fa8257b906ea093f3ce967328da780..718d11e60f7ba30d32e0dba5d08543fcf9e2fa32 100644 (file)
@@ -109,6 +109,32 @@ func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) {
        }
 }
 
+func (c *UDPConn) writeToAddrPort(b []byte, addr netip.AddrPort) (int, error) {
+       if c.fd.isConnected {
+               return 0, ErrWriteToConnected
+       }
+       if !addr.IsValid() {
+               return 0, errMissingAddress
+       }
+
+       switch c.fd.family {
+       case syscall.AF_INET:
+               sa, err := addrPortToSockaddrInet4(addr)
+               if err != nil {
+                       return 0, err
+               }
+               return c.fd.writeToInet4(b, sa)
+       case syscall.AF_INET6:
+               sa, err := addrPortToSockaddrInet6(addr)
+               if err != nil {
+                       return 0, err
+               }
+               return c.fd.writeToInet6(b, sa)
+       default:
+               return 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()}
+       }
+}
+
 func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
        if c.fd.isConnected && addr != nil {
                return 0, 0, ErrWriteToConnected