]> Cypherpunks repositories - gostls13.git/commitdiff
net: remove the alloc from WriteMsgUDPAddrPort
authorJosh Bleecher Snyder <josharian@gmail.com>
Wed, 3 Nov 2021 21:08:43 +0000 (14:08 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Thu, 4 Nov 2021 21:50:21 +0000 (21:50 +0000)
name                       old time/op    new time/op    delta
ReadWriteMsgUDPAddrPort-8    5.12µs ± 8%    4.59µs ± 3%  -10.19%  (p=0.000 n=10+9)

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

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

Change-Id: Idf540b2f9f8035660305a0ab1cfc3e162569db63
Reviewed-on: https://go-review.googlesource.com/c/go/+/361257
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/internal/poll/fd_unix.go
src/internal/poll/fd_windows.go
src/internal/syscall/unix/net.go
src/internal/syscall/unix/net_js.go
src/net/fd_posix.go
src/net/net_fake.go
src/net/udpsock_posix.go
src/syscall/syscall_unix.go

index fd5ac858501d3fee11eca02f96984161bc897ee1..b090e5b6bdc1546dc62cea755125dfa6edee5259 100644 (file)
@@ -485,6 +485,58 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err
        }
 }
 
+// WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
+func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int, int, error) {
+       if err := fd.writeLock(); err != nil {
+               return 0, 0, err
+       }
+       defer fd.writeUnlock()
+       if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+               return 0, 0, err
+       }
+       for {
+               n, err := unix.SendmsgNInet4(fd.Sysfd, p, oob, sa, 0)
+               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 n, 0, err
+               }
+               return n, len(oob), err
+       }
+}
+
+// WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
+func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (int, int, error) {
+       if err := fd.writeLock(); err != nil {
+               return 0, 0, err
+       }
+       defer fd.writeUnlock()
+       if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+               return 0, 0, err
+       }
+       for {
+               n, err := unix.SendmsgNInet6(fd.Sysfd, p, oob, sa, 0)
+               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 n, 0, err
+               }
+               return n, len(oob), err
+       }
+}
+
 // Accept wraps the accept network call.
 func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) {
        if err := fd.readLock(); err != nil {
index 139f78a7c15e78bd059f15c7c702780c7f95eb48..f8fc4de75df882c1992ce7ea7a91b57d58e77b7d 100644 (file)
@@ -1128,25 +1128,35 @@ func (fd *FD) RawWrite(f func(uintptr) bool) error {
        return syscall.EWINDOWS
 }
 
+func sockaddrInet4ToRaw(sa syscall.SockaddrInet4) (unsafe.Pointer, int32) {
+       var raw syscall.RawSockaddrInet4
+       raw.Family = syscall.AF_INET
+       p := (*[2]byte)(unsafe.Pointer(&raw.Port))
+       p[0] = byte(sa.Port >> 8)
+       p[1] = byte(sa.Port)
+       raw.Addr = sa.Addr
+       return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw))
+}
+
+func sockaddrInet6ToRaw(sa syscall.SockaddrInet6) (unsafe.Pointer, int32) {
+       var raw syscall.RawSockaddrInet6
+       raw.Family = syscall.AF_INET6
+       p := (*[2]byte)(unsafe.Pointer(&raw.Port))
+       p[0] = byte(sa.Port >> 8)
+       p[1] = byte(sa.Port)
+       raw.Scope_id = sa.ZoneId
+       raw.Addr = sa.Addr
+       return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw))
+}
+
 func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) {
        switch sa := sa.(type) {
        case *syscall.SockaddrInet4:
-               var raw syscall.RawSockaddrInet4
-               raw.Family = syscall.AF_INET
-               p := (*[2]byte)(unsafe.Pointer(&raw.Port))
-               p[0] = byte(sa.Port >> 8)
-               p[1] = byte(sa.Port)
-               raw.Addr = sa.Addr
-               return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil
+               ptr, sz := sockaddrInet4ToRaw(*sa)
+               return ptr, sz, nil
        case *syscall.SockaddrInet6:
-               var raw syscall.RawSockaddrInet6
-               raw.Family = syscall.AF_INET6
-               p := (*[2]byte)(unsafe.Pointer(&raw.Port))
-               p[0] = byte(sa.Port >> 8)
-               p[1] = byte(sa.Port)
-               raw.Scope_id = sa.ZoneId
-               raw.Addr = sa.Addr
-               return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil
+               ptr, sz := sockaddrInet6ToRaw(*sa)
+               return ptr, sz, nil
        default:
                return nil, 0, syscall.EWINDOWS
        }
@@ -1206,3 +1216,47 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err
        })
        return n, int(o.msg.Control.Len), err
 }
+
+// WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
+func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int, int, error) {
+       if len(p) > maxRW {
+               return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
+       }
+
+       if err := fd.writeLock(); err != nil {
+               return 0, 0, err
+       }
+       defer fd.writeUnlock()
+
+       o := &fd.wop
+       o.InitMsg(p, oob)
+       rsa, len := sockaddrInet4ToRaw(sa)
+       o.msg.Name = (syscall.Pointer)(rsa)
+       o.msg.Namelen = len
+       n, err := execIO(o, func(o *operation) error {
+               return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
+       })
+       return n, int(o.msg.Control.Len), err
+}
+
+// WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
+func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (int, int, error) {
+       if len(p) > maxRW {
+               return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
+       }
+
+       if err := fd.writeLock(); err != nil {
+               return 0, 0, err
+       }
+       defer fd.writeUnlock()
+
+       o := &fd.wop
+       o.InitMsg(p, oob)
+       rsa, len := sockaddrInet6ToRaw(sa)
+       o.msg.Name = (syscall.Pointer)(rsa)
+       o.msg.Namelen = len
+       n, err := execIO(o, func(o *operation) error {
+               return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
+       })
+       return n, int(o.msg.Control.Len), err
+}
index 773cf34d96624533ead2771e1d4ce4593aca23f0..71e50f54c35cf1fe01bd3ea3de5d27de52d20733 100644 (file)
@@ -26,3 +26,11 @@ func SendtoInet4(fd int, p []byte, flags int, to syscall.SockaddrInet4) (err err
 //go:linkname SendtoInet6 syscall.sendtoInet6
 //go:noescape
 func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error)
+
+//go:linkname SendmsgNInet4 syscall.sendmsgNInet4
+//go:noescape
+func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (n int, err error)
+
+//go:linkname SendmsgNInet6 syscall.sendmsgNInet6
+//go:noescape
+func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error)
index 3fc5a664703fbf8d5531fd339cbe0af57f1da9c9..35bc687b5845030ac1c749336e04c1998431f458 100644 (file)
@@ -26,3 +26,11 @@ func SendtoInet4(fd int, p []byte, flags int, to syscall.SockaddrInet4) (err err
 func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error) {
        return syscall.ENOSYS
 }
+
+func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (n int, err error) {
+       return 0, syscall.ENOSYS
+}
+
+func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) {
+       return 0, syscall.ENOSYS
+}
index 1887a451867e50b0aea39ff97d77c5d9e4e141a5..edcef1f2e18e3773db7a831230d6185d743a81f4 100644 (file)
@@ -110,6 +110,18 @@ func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
        return n, oobn, wrapSyscallError(writeMsgSyscallName, err)
 }
 
+func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) {
+       n, oobn, err = fd.pfd.WriteMsgInet4(p, oob, sa)
+       runtime.KeepAlive(fd)
+       return n, oobn, wrapSyscallError(writeMsgSyscallName, err)
+}
+
+func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (n int, oobn int, err error) {
+       n, oobn, err = fd.pfd.WriteMsgInet6(p, oob, sa)
+       runtime.KeepAlive(fd)
+       return n, oobn, wrapSyscallError(writeMsgSyscallName, err)
+}
+
 func (fd *netFD) SetDeadline(t time.Time) error {
        return fd.pfd.SetDeadline(t)
 }
index d58bd8202980028b2c5ce23ad3ae1829ff653c5f..2ade9f777455e094fc7b4f890566fe9f194b5ecc 100644 (file)
@@ -279,6 +279,14 @@ func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int
        return 0, 0, 0, nil, syscall.ENOSYS
 }
 
+func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) {
+       return 0, 0, syscall.ENOSYS
+}
+
+func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (n int, oobn int, err error) {
+       return 0, 0, syscall.ENOSYS
+}
+
 func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
        return 0, syscall.ENOSYS
 }
index c93994f836f17035712fe2d40eb1d6a332951d71..468afbc4dc69433209b7968ca67e49407b14f4c0 100644 (file)
@@ -188,15 +188,13 @@ func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn
                if err != nil {
                        return 0, 0, err
                }
-               // TODO: Implement writeMsgInet4 to avoid allocation converting sa to an interface.
-               return c.fd.writeMsg(b, oob, &sa)
+               return c.fd.writeMsgInet4(b, oob, sa)
        case syscall.AF_INET6:
                sa, err := addrPortToSockaddrInet6(addr)
                if err != nil {
                        return 0, 0, err
                }
-               // TODO: Implement writeMsgInet6 to avoid allocation converting sa to an interface.
-               return c.fd.writeMsg(b, oob, &sa)
+               return c.fd.writeMsgInet6(b, oob, sa)
        default:
                return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()}
        }
index d1ecc361c6aa2d6e22de09967cfaccabbfa02528..8692a657947c4365d5088c814d6a71f1c006d875 100644 (file)
@@ -351,6 +351,22 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
        return sendmsgN(fd, p, oob, ptr, salen, flags)
 }
 
+func sendmsgNInet4(fd int, p, oob []byte, to SockaddrInet4, flags int) (n int, err error) {
+       ptr, salen, err := to.sockaddr()
+       if err != nil {
+               return 0, err
+       }
+       return sendmsgN(fd, p, oob, ptr, salen, flags)
+}
+
+func sendmsgNInet6(fd int, p, oob []byte, to SockaddrInet6, flags int) (n int, err error) {
+       ptr, salen, err := to.sockaddr()
+       if err != nil {
+               return 0, err
+       }
+       return sendmsgN(fd, p, oob, ptr, salen, flags)
+}
+
 func sendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) {
        ptr, n, err := to.sockaddr()
        if err != nil {