From 3c61cb3dcd888fdef1c7456be144a1c4a44272a7 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 1 Nov 2021 12:44:43 -0700 Subject: [PATCH] net: optimize ReadMsgUDPAddrPort MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Instead of implementing ReadMsgUDPAddrPort in terms of ReadMsgUDP, do it the other way around. This keeps the code minimal while still avoiding allocs. We could also rearrange ReadMsgUDP to be mid-stack inlined to avoid allocating the *UDPAddr, but anyone who's trying to eliminate allocs should use ReadMsgUDPAddrPort instead anyway, because ReadMsgUDP will always allocate at least once (the IP slice). name old time/op new time/op delta ReadWriteMsgUDPAddrPort-8 5.26µs ± 3% 5.29µs ± 6% ~ (p=0.429 n=12+13) name old alloc/op new alloc/op delta ReadWriteMsgUDPAddrPort-8 176B ± 0% 128B ± 0% -27.27% (p=0.000 n=15+15) name old allocs/op new allocs/op delta ReadWriteMsgUDPAddrPort-8 5.00 ± 0% 4.00 ± 0% -20.00% (p=0.000 n=15+15) Change-Id: I15228cb4ec4f13f2f390407b6c62c44c228e7201 Reviewed-on: https://go-review.googlesource.com/c/go/+/360596 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/udpsock.go | 22 +++++++++------------- src/net/udpsock_plan9.go | 5 +++-- src/net/udpsock_posix.go | 9 ++++++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/net/udpsock.go b/src/net/udpsock.go index 95ffa85939..8c97ca7537 100644 --- a/src/net/udpsock.go +++ b/src/net/udpsock.go @@ -168,8 +168,16 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { // The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be // used to manipulate IP-level socket options in oob. func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { + var ap netip.AddrPort + n, oobn, flags, ap, err = c.ReadMsgUDPAddrPort(b, oob) + addr = UDPAddrFromAddrPort(ap) + return +} + +// ReadMsgUDPAddrPort is like ReadMsgUDP but returns an netip.AddrPort instead of a UDPAddr. +func (c *UDPConn) ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { if !c.ok() { - return 0, 0, 0, nil, syscall.EINVAL + return 0, 0, 0, netip.AddrPort{}, syscall.EINVAL } n, oobn, flags, addr, err = c.readMsg(b, oob) if err != nil { @@ -178,18 +186,6 @@ func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, return } -// ReadMsgUDPAddrPort is like ReadMsgUDP but returns an netip.AddrPort instead of a UDPAddr. -func (c *UDPConn) ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err 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. - var ua *UDPAddr - n, oobn, flags, ua, err = c.ReadMsgUDP(b, oob) - addr = ua.AddrPort() - return -} - // WriteToUDP acts like WriteTo but takes a UDPAddr. func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { if !c.ok() { diff --git a/src/net/udpsock_plan9.go b/src/net/udpsock_plan9.go index 1df293d1db..c18af2356d 100644 --- a/src/net/udpsock_plan9.go +++ b/src/net/udpsock_plan9.go @@ -7,6 +7,7 @@ package net import ( "context" "errors" + "net/netip" "os" "syscall" ) @@ -28,8 +29,8 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { return n, addr, nil } -func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { - return 0, 0, 0, nil, syscall.EPLAN9 +func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { + return 0, 0, 0, netip.AddrPort{}, syscall.EPLAN9 } func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index c3f7ddb77e..b20025140f 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -8,6 +8,7 @@ package net import ( "context" + "net/netip" "syscall" ) @@ -68,14 +69,16 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { return n, addr, err } -func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { +func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { var sa syscall.Sockaddr n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0) switch sa := sa.(type) { case *syscall.SockaddrInet4: - addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port} + ip := netip.AddrFrom4(sa.Addr) + addr = netip.AddrPortFrom(ip, uint16(sa.Port)) case *syscall.SockaddrInet6: - addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))} + ip := netip.AddrFrom16(sa.Addr).WithZone(zoneCache.name(int(sa.ZoneId))) + addr = netip.AddrPortFrom(ip, uint16(sa.Port)) } return } -- 2.50.0