1
0
mirror of https://github.com/golang/go synced 2024-11-24 07:50:13 -07:00

net: remove the alloc from WriteMsgUDPAddrPort

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>
This commit is contained in:
Josh Bleecher Snyder 2021-11-03 14:08:43 -07:00
parent 156abe5122
commit bfd74fd422
8 changed files with 175 additions and 19 deletions

View 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 {

View 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
}

View 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)

View 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
}

View 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)
}

View 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
}

View 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()}
}

View 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 {