net: remove the alloc from ReadMsgUDPAddrPort

name                          old time/op    new time/op    delta
ReadWriteMsgUDPAddrPort-8       4.95µs ± 5%    4.55µs ± 1%    -7.96%  (p=0.016 n=5+4)

name                          old alloc/op   new alloc/op   delta
ReadWriteMsgUDPAddrPort-8        32.0B ± 0%      0.0B       -100.00%  (p=0.008 n=5+5)

name                          old allocs/op  new allocs/op  delta
ReadWriteMsgUDPAddrPort-8         1.00 ± 0%      0.00       -100.00%  (p=0.008 n=5+5)

Change-Id: Ib968c6f2968926ec9a364dd52063cd0d7c29b10c
Reviewed-on: https://go-review.googlesource.com/c/go/+/360862
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:42:52 -07:00
parent bfd74fd422
commit 37634eeff9
8 changed files with 195 additions and 13 deletions

View file

@ -311,6 +311,60 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S
} }
} }
// ReadMsgInet4 is ReadMsg, but specialized for syscall.SockaddrInet4.
func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) {
if err := fd.readLock(); err != nil {
return 0, 0, 0, err
}
defer fd.readUnlock()
if err := fd.pd.prepareRead(fd.isFile); err != nil {
return 0, 0, 0, err
}
for {
n, oobn, sysflags, err := unix.RecvmsgInet4(fd.Sysfd, p, oob, flags, sa4)
if err != nil {
if err == syscall.EINTR {
continue
}
// TODO(dfc) should n and oobn be set to 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, oobn, sysflags, err
}
}
// ReadMsgInet6 is ReadMsg, but specialized for syscall.SockaddrInet6.
func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) {
if err := fd.readLock(); err != nil {
return 0, 0, 0, err
}
defer fd.readUnlock()
if err := fd.pd.prepareRead(fd.isFile); err != nil {
return 0, 0, 0, err
}
for {
n, oobn, sysflags, err := unix.RecvmsgInet6(fd.Sysfd, p, oob, flags, sa6)
if err != nil {
if err == syscall.EINTR {
continue
}
// TODO(dfc) should n and oobn be set to 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, oobn, sysflags, err
}
}
// Write implements io.Writer. // Write implements io.Writer.
func (fd *FD) Write(p []byte) (int, error) { func (fd *FD) Write(p []byte) (int, error) {
if err := fd.writeLock(); err != nil { if err := fd.writeLock(); err != nil {

View file

@ -620,10 +620,7 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error)
if err != nil { if err != nil {
return n, err return n, err
} }
sa, _ := o.rsa.Sockaddr() rawToSockaddrInet4(o.rsa, sa4)
if sa != nil {
*sa4 = *(sa.(*syscall.SockaddrInet4))
}
return n, err return n, err
} }
@ -652,10 +649,7 @@ func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error)
if err != nil { if err != nil {
return n, err return n, err
} }
sa, _ := o.rsa.Sockaddr() rawToSockaddrInet6(o.rsa, sa6)
if sa != nil {
*sa6 = *(sa.(*syscall.SockaddrInet6))
}
return n, err return n, err
} }
@ -1149,6 +1143,21 @@ func sockaddrInet6ToRaw(sa syscall.SockaddrInet6) (unsafe.Pointer, int32) {
return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)) return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw))
} }
func rawToSockaddrInet4(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) {
pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.Addr = pp.Addr
}
func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) {
pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
sa.Addr = pp.Addr
}
func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) {
switch sa := sa.(type) { switch sa := sa.(type) {
case *syscall.SockaddrInet4: case *syscall.SockaddrInet4:
@ -1190,6 +1199,60 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S
return n, int(o.msg.Control.Len), int(o.msg.Flags), sa, err return n, int(o.msg.Control.Len), int(o.msg.Flags), sa, err
} }
// ReadMsgInet4 is ReadMsg, but specialized to return a syscall.SockaddrInet4.
func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) {
if err := fd.readLock(); err != nil {
return 0, 0, 0, err
}
defer fd.readUnlock()
if len(p) > maxRW {
p = p[:maxRW]
}
o := &fd.rop
o.InitMsg(p, oob)
o.rsa = new(syscall.RawSockaddrAny)
o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
o.msg.Flags = uint32(flags)
n, err := execIO(o, func(o *operation) error {
return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
})
err = fd.eofError(n, err)
if err == nil {
rawToSockaddrInet4(o.rsa, sa4)
}
return n, int(o.msg.Control.Len), int(o.msg.Flags), err
}
// ReadMsgInet6 is ReadMsg, but specialized to return a syscall.SockaddrInet6.
func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) {
if err := fd.readLock(); err != nil {
return 0, 0, 0, err
}
defer fd.readUnlock()
if len(p) > maxRW {
p = p[:maxRW]
}
o := &fd.rop
o.InitMsg(p, oob)
o.rsa = new(syscall.RawSockaddrAny)
o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
o.msg.Flags = uint32(flags)
n, err := execIO(o, func(o *operation) error {
return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
})
err = fd.eofError(n, err)
if err == nil {
rawToSockaddrInet6(o.rsa, sa6)
}
return n, int(o.msg.Control.Len), int(o.msg.Flags), err
}
// WriteMsg wraps the WSASendMsg network call. // WriteMsg wraps the WSASendMsg network call.
func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) { func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
if len(p) > maxRW { if len(p) > maxRW {

View file

@ -34,3 +34,11 @@ func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (
//go:linkname SendmsgNInet6 syscall.sendmsgNInet6 //go:linkname SendmsgNInet6 syscall.sendmsgNInet6
//go:noescape //go:noescape
func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error)
//go:linkname RecvmsgInet4 syscall.recvmsgInet4
//go:noescape
func RecvmsgInet4(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet4) (n, oobn int, recvflags int, err error)
//go:linkname RecvmsgInet6 syscall.recvmsgInet6
//go:noescape
func RecvmsgInet6(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet6) (n, oobn int, recvflags int, err error)

View file

@ -34,3 +34,11 @@ func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (
func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) { func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) {
return 0, syscall.ENOSYS return 0, syscall.ENOSYS
} }
func RecvmsgInet4(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet4) (n, oobn int, recvflags int, err error) {
return 0, 0, 0, syscall.ENOSYS
}
func RecvmsgInet6(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet6) (n, oobn int, recvflags int, err error) {
return 0, 0, 0, syscall.ENOSYS
}

View file

@ -80,6 +80,18 @@ func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int
return n, oobn, retflags, sa, wrapSyscallError(readMsgSyscallName, err) return n, oobn, retflags, sa, wrapSyscallError(readMsgSyscallName, err)
} }
func (fd *netFD) readMsgInet4(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet4) (n, oobn, retflags int, err error) {
n, oobn, retflags, err = fd.pfd.ReadMsgInet4(p, oob, flags, sa)
runtime.KeepAlive(fd)
return n, oobn, retflags, wrapSyscallError(readMsgSyscallName, err)
}
func (fd *netFD) readMsgInet6(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet6) (n, oobn, retflags int, err error) {
n, oobn, retflags, err = fd.pfd.ReadMsgInet6(p, oob, flags, sa)
runtime.KeepAlive(fd)
return n, oobn, retflags, wrapSyscallError(readMsgSyscallName, err)
}
func (fd *netFD) Write(p []byte) (nn int, err error) { func (fd *netFD) Write(p []byte) (nn int, err error) {
nn, err = fd.pfd.Write(p) nn, err = fd.pfd.Write(p)
runtime.KeepAlive(fd) runtime.KeepAlive(fd)

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 return 0, 0, 0, nil, syscall.ENOSYS
} }
func (fd *netFD) readMsgInet4(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet4) (n, oobn, retflags int, err error) {
return 0, 0, 0, syscall.ENOSYS
}
func (fd *netFD) readMsgInet6(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet6) (n, oobn, retflags int, err error) {
return 0, 0, 0, syscall.ENOSYS
}
func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) { func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) {
return 0, 0, syscall.ENOSYS return 0, 0, syscall.ENOSYS
} }

View file

@ -95,13 +95,15 @@ func (c *UDPConn) readFromAddrPort(b []byte) (n int, addr netip.AddrPort, err er
} }
func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) {
var sa syscall.Sockaddr switch c.fd.family {
n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0) case syscall.AF_INET:
switch sa := sa.(type) { var sa syscall.SockaddrInet4
case *syscall.SockaddrInet4: n, oobn, flags, err = c.fd.readMsgInet4(b, oob, 0, &sa)
ip := netip.AddrFrom4(sa.Addr) ip := netip.AddrFrom4(sa.Addr)
addr = netip.AddrPortFrom(ip, uint16(sa.Port)) addr = netip.AddrPortFrom(ip, uint16(sa.Port))
case *syscall.SockaddrInet6: case syscall.AF_INET6:
var sa syscall.SockaddrInet6
n, oobn, flags, err = c.fd.readMsgInet6(b, oob, 0, &sa)
ip := netip.AddrFrom16(sa.Addr).WithZone(zoneCache.name(int(sa.ZoneId))) ip := netip.AddrFrom16(sa.Addr).WithZone(zoneCache.name(int(sa.ZoneId)))
addr = netip.AddrPortFrom(ip, uint16(sa.Port)) addr = netip.AddrPortFrom(ip, uint16(sa.Port))
} }

View file

@ -324,6 +324,33 @@ func recvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err
return return
} }
func recvmsgInet4(fd int, p, oob []byte, flags int, from *SockaddrInet4) (n, oobn int, recvflags int, err error) {
var rsa RawSockaddrAny
n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)
if 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 recvmsgInet6(fd int, p, oob []byte, flags int, from *SockaddrInet6) (n, oobn int, recvflags int, err error) {
var rsa RawSockaddrAny
n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)
if 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 Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
var rsa RawSockaddrAny var rsa RawSockaddrAny
n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa) n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)