]> Cypherpunks repositories - gostls13.git/commitdiff
net: reduce allocation size in ReadFromUDP
authorJosh Bleecher Snyder <josharian@gmail.com>
Fri, 12 Feb 2021 03:34:22 +0000 (19:34 -0800)
committerDamien Neil <dneil@google.com>
Mon, 16 Aug 2021 23:57:02 +0000 (23:57 +0000)
Switch to concrete types. Bring your own object to fill in.

Allocate just enough for the IP byte slice.
The allocation is now just 4 bytes for IPv4,
which puts it in the tiny allocator, which is much faster.

name                  old time/op    new time/op    delta
WriteToReadFromUDP-8    13.7µs ± 1%    13.4µs ± 2%   -2.49%  (p=0.000 n=10+10)

name                  old alloc/op   new alloc/op   delta
WriteToReadFromUDP-8     32.0B ± 0%      4.0B ± 0%  -87.50%  (p=0.000 n=10+10)

name                  old allocs/op  new allocs/op  delta
WriteToReadFromUDP-8      1.00 ± 0%      1.00 ± 0%     ~     (all equal)

Windows is temporarily stubbed out.

Updates #43451

Change-Id: Ief506f891b401d28715d22dce6ebda037941924e
Reviewed-on: https://go-review.googlesource.com/c/go/+/331490
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Trust: Damien Neil <dneil@google.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Damien Neil <dneil@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
api/next.txt
src/internal/poll/fd_unix.go
src/internal/poll/fd_windows.go
src/net/fd_posix.go
src/net/net_fake.go
src/net/udpsock_posix.go
src/syscall/net_js.go
src/syscall/syscall_unix.go

index 8d2ee73f79d4fe3cabe5d016fcdacea263b6e28d..4dbaae3cf205af4f86f0d96798b924ba606248a7 100644 (file)
+pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (darwin-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (darwin-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (darwin-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (darwin-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (freebsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (freebsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (freebsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (freebsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (freebsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (freebsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (freebsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (freebsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (freebsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (freebsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (freebsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (freebsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (freebsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (freebsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (freebsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (linux-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (linux-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (linux-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (linux-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (linux-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (linux-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (linux-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (linux-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (linux-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (linux-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (linux-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (linux-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (linux-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (linux-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (linux-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (netbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (netbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (netbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (netbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (netbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (netbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (netbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (netbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (netbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (netbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (netbsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (netbsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (netbsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (netbsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (netbsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-arm64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (netbsd-arm64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (netbsd-arm64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (netbsd-arm64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-arm64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (netbsd-arm64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (netbsd-arm64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (openbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (openbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (openbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (openbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (openbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (openbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (openbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (openbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (openbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (openbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (openbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (openbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
+pkg syscall (openbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
 pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
index 51d15f6abce9a33ea4eca42262e61b620f8a0305..60b59df2e36a3f73f39665fc264a0d52329b772e 100644 (file)
@@ -230,6 +230,60 @@ func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) {
        }
 }
 
+// ReadFrom wraps the recvfrom network call for IPv4.
+func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) {
+       if err := fd.readLock(); err != nil {
+               return 0, err
+       }
+       defer fd.readUnlock()
+       if err := fd.pd.prepareRead(fd.isFile); err != nil {
+               return 0, err
+       }
+       for {
+               n, err := syscall.RecvfromInet4(fd.Sysfd, p, 0, from)
+               if err != nil {
+                       if err == syscall.EINTR {
+                               continue
+                       }
+                       n = 0
+                       if err == syscall.EAGAIN && fd.pd.pollable() {
+                               if err = fd.pd.waitRead(fd.isFile); err == nil {
+                                       continue
+                               }
+                       }
+               }
+               err = fd.eofError(n, err)
+               return n, err
+       }
+}
+
+// ReadFrom wraps the recvfrom network call for IPv6.
+func (fd *FD) ReadFromInet6(p []byte, from *syscall.SockaddrInet6) (int, error) {
+       if err := fd.readLock(); err != nil {
+               return 0, err
+       }
+       defer fd.readUnlock()
+       if err := fd.pd.prepareRead(fd.isFile); err != nil {
+               return 0, err
+       }
+       for {
+               n, err := syscall.RecvfromInet6(fd.Sysfd, p, 0, from)
+               if err != nil {
+                       if err == syscall.EINTR {
+                               continue
+                       }
+                       n = 0
+                       if err == syscall.EAGAIN && fd.pd.pollable() {
+                               if err = fd.pd.waitRead(fd.isFile); err == nil {
+                                       continue
+                               }
+                       }
+               }
+               err = fd.eofError(n, err)
+               return n, err
+       }
+}
+
 // ReadMsg wraps the recvmsg network call.
 func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
        if err := fd.readLock(); err != nil {
index 3dada329854973c69b4fd6f4700ad2b2ffef9f36..14e8f4965b963eb0796da8971d7df9aa624a5c92 100644 (file)
@@ -593,6 +593,24 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
        return n, sa, nil
 }
 
+// ReadFrom wraps the recvfrom network call for IPv4.
+func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
+       n, sa, err := fd.ReadFrom(buf)
+       if sa != nil {
+               *sa4 = *(sa.(*syscall.SockaddrInet4))
+       }
+       return n, err
+}
+
+// ReadFrom wraps the recvfrom network call for IPv6.
+func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
+       n, sa, err := fd.ReadFrom(buf)
+       if sa != nil {
+               *sa6 = *(sa.(*syscall.SockaddrInet6))
+       }
+       return n, err
+}
+
 // Write implements io.Writer.
 func (fd *FD) Write(buf []byte) (int, error) {
        if err := fd.writeLock(); err != nil {
index a0675b20724b279b8ae8958c2ed76b1f6d71a2fa..38e5a8d61d10533a5c7b1f8b044cacf01dd24237 100644 (file)
@@ -63,6 +63,17 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
        runtime.KeepAlive(fd)
        return n, sa, wrapSyscallError(readFromSyscallName, err)
 }
+func (fd *netFD) readFromInet4(p []byte, from *syscall.SockaddrInet4) (n int, err error) {
+       n, err = fd.pfd.ReadFromInet4(p, from)
+       runtime.KeepAlive(fd)
+       return n, wrapSyscallError(readFromSyscallName, err)
+}
+
+func (fd *netFD) readFromInet6(p []byte, from *syscall.SockaddrInet6) (n int, err error) {
+       n, err = fd.pfd.ReadFromInet6(p, from)
+       runtime.KeepAlive(fd)
+       return n, wrapSyscallError(readFromSyscallName, err)
+}
 
 func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {
        n, oobn, retflags, sa, err = fd.pfd.ReadMsg(p, oob, flags)
index feb51968dd34d48eb291ee1a72aca9c0b8ffd19d..48419be6703ac7caeaaadc46157be59d068922cb 100644 (file)
@@ -266,6 +266,14 @@ func sysSocket(family, sotype, proto int) (int, error) {
 
 func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
        return 0, nil, syscall.ENOSYS
+
+}
+func (fd *netFD) readFromInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) {
+       return 0, syscall.ENOSYS
+}
+
+func (fd *netFD) readFromInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) {
+       return 0, syscall.ENOSYS
 }
 
 func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {
index b71be092170c80c52ecdd1f2c5b6c8d6323d36b5..3a333ca2438250c9f6848302aea6f3ff0291725e 100644 (file)
@@ -44,13 +44,25 @@ func (a *UDPAddr) toLocal(net string) sockaddr {
 }
 
 func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) {
-       n, sa, err := c.fd.readFrom(b)
-       switch sa := sa.(type) {
-       case *syscall.SockaddrInet4:
-               *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
-       case *syscall.SockaddrInet6:
-               *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
-       default:
+       var n int
+       var err error
+       switch c.fd.family {
+       case syscall.AF_INET:
+               var from syscall.SockaddrInet4
+               n, err = c.fd.readFromInet4(b, &from)
+               if err == nil {
+                       ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 4 bytes
+                       *addr = UDPAddr{IP: ip[:], Port: from.Port}
+               }
+       case syscall.AF_INET6:
+               var from syscall.SockaddrInet6
+               n, err = c.fd.readFromInet6(b, &from)
+               if err == nil {
+                       ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 16 bytes
+                       *addr = UDPAddr{IP: ip[:], Port: from.Port, Zone: zoneCache.name(int(from.ZoneId))}
+               }
+       }
+       if err != nil {
                // No sockaddr, so don't return UDPAddr.
                addr = nil
        }
index 17799148bdee813a40f00e146458f07d63996be1..2998c2159c8ef77d35ceb10846d08bfb17604851 100644 (file)
@@ -92,6 +92,14 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
        return 0, nil, ENOSYS
 }
 
+func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) {
+       return 0, ENOSYS
+}
+
+func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) {
+       return 0, ENOSYS
+}
+
 func Sendto(fd int, p []byte, flags int, to Sockaddr) error {
        return ENOSYS
 }
index 60aeae14de4f1fad1586753cf4a12437247c429e..101e39c7d0885395ac8d84438a2ff6092cd6aa2a 100644 (file)
@@ -292,6 +292,33 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
        return
 }
 
+func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) {
+       var rsa RawSockaddrAny
+       var socklen _Socklen = SizeofSockaddrAny
+       if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil {
+               return
+       }
+       pp := (*RawSockaddrInet4)(unsafe.Pointer(&rsa))
+       port := (*[2]byte)(unsafe.Pointer(&pp.Port))
+       from.Port = int(port[0])<<8 + int(port[1])
+       from.Addr = pp.Addr
+       return
+}
+
+func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) {
+       var rsa RawSockaddrAny
+       var socklen _Socklen = SizeofSockaddrAny
+       if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil {
+               return
+       }
+       pp := (*RawSockaddrInet6)(unsafe.Pointer(&rsa))
+       port := (*[2]byte)(unsafe.Pointer(&pp.Port))
+       from.Port = int(port[0])<<8 + int(port[1])
+       from.ZoneId = pp.Scope_id
+       from.Addr = pp.Addr
+       return
+}
+
 func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) {
        ptr, n, err := to.sockaddr()
        if err != nil {