]> Cypherpunks repositories - gostls13.git/commitdiff
net: remove allocation from UDPConn.WriteTo
authorJosh Bleecher Snyder <josharian@gmail.com>
Wed, 26 May 2021 19:55:16 +0000 (12:55 -0700)
committerDamien Neil <dneil@google.com>
Mon, 16 Aug 2021 23:54:32 +0000 (23:54 +0000)
Duplicate some code to avoid an interface.

name                  old time/op    new time/op    delta
WriteToReadFromUDP-8    6.38µs ±20%    5.59µs ±10%  -12.38%  (p=0.001 n=10+9)

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

name                  old allocs/op  new allocs/op  delta
WriteToReadFromUDP-8      2.00 ± 0%      1.00 ± 0%  -50.00%  (p=0.000 n=10+10)

Windows is temporarily stubbed out.

Updates #43451

Change-Id: Ied15ff92268c652cf445836e0446025eaeb60cc9
Reviewed-on: https://go-review.googlesource.com/c/go/+/331489
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Trust: Damien Neil <dneil@google.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
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/ipsock_posix.go
src/net/net_fake.go
src/net/udpsock_posix.go
src/syscall/net_js.go
src/syscall/syscall_unix.go

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8d2ee73f79d4fe3cabe5d016fcdacea263b6e28d 100644 (file)
@@ -0,0 +1,52 @@
+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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) 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 SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
index 3b17cd22b03b8f85d0f9b6eb250d3379d59b9cfa..51d15f6abce9a33ea4eca42262e61b620f8a0305 100644 (file)
@@ -327,6 +327,58 @@ func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
        }
 }
 
+// WriteToInet4 wraps the sendto network call for IPv4 addresses.
+func (fd *FD) WriteToInet4(p []byte, sa syscall.SockaddrInet4) (int, error) {
+       if err := fd.writeLock(); err != nil {
+               return 0, err
+       }
+       defer fd.writeUnlock()
+       if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+               return 0, err
+       }
+       for {
+               err := syscall.SendtoInet4(fd.Sysfd, p, 0, sa)
+               if err == syscall.EINTR {
+                       continue
+               }
+               if err == syscall.EAGAIN && fd.pd.pollable() {
+                       if err = fd.pd.waitWrite(fd.isFile); err == nil {
+                               continue
+                       }
+               }
+               if err != nil {
+                       return 0, err
+               }
+               return len(p), nil
+       }
+}
+
+// WriteToInet6 wraps the sendto network call for IPv6 addresses.
+func (fd *FD) WriteToInet6(p []byte, sa syscall.SockaddrInet6) (int, error) {
+       if err := fd.writeLock(); err != nil {
+               return 0, err
+       }
+       defer fd.writeUnlock()
+       if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+               return 0, err
+       }
+       for {
+               err := syscall.SendtoInet6(fd.Sysfd, p, 0, sa)
+               if err == syscall.EINTR {
+                       continue
+               }
+               if err == syscall.EAGAIN && fd.pd.pollable() {
+                       if err = fd.pd.waitWrite(fd.isFile); err == nil {
+                               continue
+                       }
+               }
+               if err != nil {
+                       return 0, err
+               }
+               return len(p), nil
+       }
+}
+
 // WriteTo wraps the sendto network call.
 func (fd *FD) WriteTo(p []byte, sa syscall.Sockaddr) (int, error) {
        if err := fd.writeLock(); err != nil {
index 4a5169527c42b0592d13e6c75df3fc9773647347..3dada329854973c69b4fd6f4700ad2b2ffef9f36 100644 (file)
@@ -791,6 +791,16 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
        return ntotal, nil
 }
 
+// WriteTo wraps the sendto network call for IPv4.
+func (fd *FD) WriteToInet4(buf []byte, sa syscall.SockaddrInet4) (int, error) {
+       return fd.WriteTo(buf, &sa)
+}
+
+// WriteTo wraps the sendto network call for IPv6.
+func (fd *FD) WriteToInet6(buf []byte, sa syscall.SockaddrInet6) (int, error) {
+       return fd.WriteTo(buf, &sa)
+}
+
 // Call ConnectEx. This doesn't need any locking, since it is only
 // called when the descriptor is first created. This is here rather
 // than in the net package so that it can use fd.wop.
index 4703ff33a10c71ef22df5317f8b413cfe186e0d6..a0675b20724b279b8ae8958c2ed76b1f6d71a2fa 100644 (file)
@@ -82,6 +82,18 @@ func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
        return n, wrapSyscallError(writeToSyscallName, err)
 }
 
+func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) {
+       n, err = fd.pfd.WriteToInet4(p, sa)
+       runtime.KeepAlive(fd)
+       return n, wrapSyscallError(writeToSyscallName, err)
+}
+
+func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) {
+       n, err = fd.pfd.WriteToInet6(p, sa)
+       runtime.KeepAlive(fd)
+       return n, wrapSyscallError(writeToSyscallName, err)
+}
+
 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
        n, oobn, err = fd.pfd.WriteMsg(p, oob, sa)
        runtime.KeepAlive(fd)
index c51c2274015dcf8382e079bcb8ef3759d1a87f88..50003ac4464bc013ae5d10cb65cbc953b24ad8a6 100644 (file)
@@ -142,42 +142,58 @@ func internetSocket(ctx context.Context, net string, laddr, raddr sockaddr, soty
        return socket(ctx, net, family, sotype, proto, ipv6only, laddr, raddr, ctrlFn)
 }
 
+func ipToSockaddrInet4(ip IP, port int) (syscall.SockaddrInet4, error) {
+       if len(ip) == 0 {
+               ip = IPv4zero
+       }
+       ip4 := ip.To4()
+       if ip4 == nil {
+               return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
+       }
+       sa := syscall.SockaddrInet4{Port: port}
+       copy(sa.Addr[:], ip4)
+       return sa, nil
+}
+
+func ipToSockaddrInet6(ip IP, port int, zone string) (syscall.SockaddrInet6, error) {
+       // In general, an IP wildcard address, which is either
+       // "0.0.0.0" or "::", means the entire IP addressing
+       // space. For some historical reason, it is used to
+       // specify "any available address" on some operations
+       // of IP node.
+       //
+       // When the IP node supports IPv4-mapped IPv6 address,
+       // we allow a listener to listen to the wildcard
+       // address of both IP addressing spaces by specifying
+       // IPv6 wildcard address.
+       if len(ip) == 0 || ip.Equal(IPv4zero) {
+               ip = IPv6zero
+       }
+       // We accept any IPv6 address including IPv4-mapped
+       // IPv6 address.
+       ip6 := ip.To16()
+       if ip6 == nil {
+               return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: ip.String()}
+       }
+       sa := syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))}
+       copy(sa.Addr[:], ip6)
+       return sa, nil
+}
+
 func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
        switch family {
        case syscall.AF_INET:
-               if len(ip) == 0 {
-                       ip = IPv4zero
-               }
-               ip4 := ip.To4()
-               if ip4 == nil {
-                       return nil, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
+               sa, err := ipToSockaddrInet4(ip, port)
+               if err != nil {
+                       return nil, err
                }
-               sa := &syscall.SockaddrInet4{Port: port}
-               copy(sa.Addr[:], ip4)
-               return sa, nil
+               return &sa, nil
        case syscall.AF_INET6:
-               // In general, an IP wildcard address, which is either
-               // "0.0.0.0" or "::", means the entire IP addressing
-               // space. For some historical reason, it is used to
-               // specify "any available address" on some operations
-               // of IP node.
-               //
-               // When the IP node supports IPv4-mapped IPv6 address,
-               // we allow a listener to listen to the wildcard
-               // address of both IP addressing spaces by specifying
-               // IPv6 wildcard address.
-               if len(ip) == 0 || ip.Equal(IPv4zero) {
-                       ip = IPv6zero
-               }
-               // We accept any IPv6 address including IPv4-mapped
-               // IPv6 address.
-               ip6 := ip.To16()
-               if ip6 == nil {
-                       return nil, &AddrError{Err: "non-IPv6 address", Addr: ip.String()}
+               sa, err := ipToSockaddrInet6(ip, port, zone)
+               if err != nil {
+                       return nil, err
                }
-               sa := &syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))}
-               copy(sa.Addr[:], ip6)
-               return sa, nil
+               return &sa, nil
        }
        return nil, &AddrError{Err: "invalid address family", Addr: ip.String()}
 }
index 74fc1da6fd80af665696880153bfc49a508900d6..feb51968dd34d48eb291ee1a72aca9c0b8ffd19d 100644 (file)
@@ -276,6 +276,14 @@ func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
        return 0, syscall.ENOSYS
 }
 
+func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) {
+       return 0, syscall.ENOSYS
+}
+
+func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) {
+       return 0, syscall.ENOSYS
+}
+
 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
        return 0, 0, syscall.ENOSYS
 }
index 96fb373ce770ca91a8a8dc0eec2f1712ca381ed1..b71be092170c80c52ecdd1f2c5b6c8d6323d36b5 100644 (file)
@@ -76,11 +76,23 @@ func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) {
        if addr == nil {
                return 0, errMissingAddress
        }
-       sa, err := addr.sockaddr(c.fd.family)
-       if err != nil {
-               return 0, err
+
+       switch c.fd.family {
+       case syscall.AF_INET:
+               sa, err := ipToSockaddrInet4(addr.IP, addr.Port)
+               if err != nil {
+                       return 0, err
+               }
+               return c.fd.writeToInet4(b, sa)
+       case syscall.AF_INET6:
+               sa, err := ipToSockaddrInet6(addr.IP, addr.Port, addr.Zone)
+               if err != nil {
+                       return 0, err
+               }
+               return c.fd.writeToInet6(b, sa)
+       default:
+               return 0, &AddrError{Err: "invalid address family", Addr: addr.IP.String()}
        }
-       return c.fd.writeTo(b, sa)
 }
 
 func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
index ed462025bbc88c1d3f5e4972e51320ba1c726b25..17799148bdee813a40f00e146458f07d63996be1 100644 (file)
@@ -96,6 +96,14 @@ func Sendto(fd int, p []byte, flags int, to Sockaddr) error {
        return ENOSYS
 }
 
+func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) error {
+       return ENOSYS
+}
+
+func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) error {
+       return ENOSYS
+}
+
 func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn, recvflags int, from Sockaddr, err error) {
        return 0, 0, 0, nil, ENOSYS
 }
index 5b405b99b4f23744bb35f308ab1b8b015d3994ee..60aeae14de4f1fad1586753cf4a12437247c429e 100644 (file)
@@ -292,6 +292,22 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
        return
 }
 
+func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) {
+       ptr, n, err := to.sockaddr()
+       if err != nil {
+               return err
+       }
+       return sendto(fd, p, flags, ptr, n)
+}
+
+func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) (err error) {
+       ptr, n, err := to.sockaddr()
+       if err != nil {
+               return err
+       }
+       return sendto(fd, p, flags, ptr, n)
+}
+
 func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
        ptr, n, err := to.sockaddr()
        if err != nil {