]> Cypherpunks repositories - gostls13.git/commitdiff
net: optimize ReadMsgUDPAddrPort
authorJosh Bleecher Snyder <josharian@gmail.com>
Mon, 1 Nov 2021 19:44:43 +0000 (12:44 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 2 Nov 2021 03:54:24 +0000 (03:54 +0000)
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 <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 95ffa85939de4e7cc8a1202ccbbdcc5e034c2abe..8c97ca753775f0c81191a52ad0df93bc29ca2c9b 100644 (file)
@@ -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() {
index 1df293d1db93525d91938d8e5b291142ce9c3a6f..c18af2356d1fe3fe162152c3baab3698b9e3c1bc 100644 (file)
@@ -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) {
index c3f7ddb77eb81cadc85b20f2b8d33ea9188ffc0a..b20025140f2dd0691d3b63fc368c89fa843e13d5 100644 (file)
@@ -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
 }