Skip to content

Commit 5875cad

Browse files
committed
[tailscale1.17] net: reduce allocation size in ReadFromUDP
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 golang#43451 (cherry picked from golang.org/cl/331490) Change-Id: Ief506f891b401d28715d22dce6ebda037941924e
1 parent 85ea910 commit 5875cad

File tree

8 files changed

+197
-7
lines changed

8 files changed

+197
-7
lines changed

api/go1.tailscale.txt

+52
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,107 @@ pkg net/http, type Transport struct, OnProxyConnectResponse func(context.Context
22
pkg reflect, method (*MapIter) SetKey(Value)
33
pkg reflect, method (*MapIter) SetValue(Value)
44
pkg reflect, method (*MapIter) Reset(Value)
5+
pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
6+
pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
57
pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
68
pkg syscall (darwin-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
9+
pkg syscall (darwin-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
10+
pkg syscall (darwin-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
711
pkg syscall (darwin-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
812
pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
13+
pkg syscall (freebsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
14+
pkg syscall (freebsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
915
pkg syscall (freebsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
1016
pkg syscall (freebsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
17+
pkg syscall (freebsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
18+
pkg syscall (freebsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
1119
pkg syscall (freebsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
1220
pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
21+
pkg syscall (freebsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
22+
pkg syscall (freebsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
1323
pkg syscall (freebsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
1424
pkg syscall (freebsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
25+
pkg syscall (freebsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
26+
pkg syscall (freebsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
1527
pkg syscall (freebsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
1628
pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
29+
pkg syscall (freebsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
30+
pkg syscall (freebsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
1731
pkg syscall (freebsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
1832
pkg syscall (freebsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
33+
pkg syscall (freebsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
34+
pkg syscall (freebsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
1935
pkg syscall (freebsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
2036
pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
37+
pkg syscall (linux-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
38+
pkg syscall (linux-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
2139
pkg syscall (linux-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
2240
pkg syscall (linux-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
41+
pkg syscall (linux-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
42+
pkg syscall (linux-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
2343
pkg syscall (linux-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
2444
pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
45+
pkg syscall (linux-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
46+
pkg syscall (linux-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
2547
pkg syscall (linux-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
2648
pkg syscall (linux-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
49+
pkg syscall (linux-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
50+
pkg syscall (linux-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
2751
pkg syscall (linux-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
2852
pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
53+
pkg syscall (linux-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
54+
pkg syscall (linux-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
2955
pkg syscall (linux-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
3056
pkg syscall (linux-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
57+
pkg syscall (linux-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
58+
pkg syscall (linux-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
3159
pkg syscall (linux-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
3260
pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
61+
pkg syscall (netbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
62+
pkg syscall (netbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
3363
pkg syscall (netbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
3464
pkg syscall (netbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
65+
pkg syscall (netbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
66+
pkg syscall (netbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
3567
pkg syscall (netbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
3668
pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
69+
pkg syscall (netbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
70+
pkg syscall (netbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
3771
pkg syscall (netbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
3872
pkg syscall (netbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
73+
pkg syscall (netbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
74+
pkg syscall (netbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
3975
pkg syscall (netbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
4076
pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
77+
pkg syscall (netbsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
78+
pkg syscall (netbsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
4179
pkg syscall (netbsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
4280
pkg syscall (netbsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
81+
pkg syscall (netbsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
82+
pkg syscall (netbsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
4383
pkg syscall (netbsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
4484
pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
85+
pkg syscall (netbsd-arm64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
86+
pkg syscall (netbsd-arm64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
4587
pkg syscall (netbsd-arm64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
4688
pkg syscall (netbsd-arm64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
89+
pkg syscall (netbsd-arm64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
90+
pkg syscall (netbsd-arm64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
4791
pkg syscall (netbsd-arm64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
4892
pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
93+
pkg syscall (openbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
94+
pkg syscall (openbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
4995
pkg syscall (openbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
5096
pkg syscall (openbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
97+
pkg syscall (openbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
98+
pkg syscall (openbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
5199
pkg syscall (openbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
52100
pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
101+
pkg syscall (openbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
102+
pkg syscall (openbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
53103
pkg syscall (openbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
54104
pkg syscall (openbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
105+
pkg syscall (openbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
106+
pkg syscall (openbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
55107
pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
56108
pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error

src/internal/poll/fd_unix.go

+54
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,60 @@ func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) {
230230
}
231231
}
232232

233+
// ReadFrom wraps the recvfrom network call for IPv4.
234+
func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) {
235+
if err := fd.readLock(); err != nil {
236+
return 0, err
237+
}
238+
defer fd.readUnlock()
239+
if err := fd.pd.prepareRead(fd.isFile); err != nil {
240+
return 0, err
241+
}
242+
for {
243+
n, err := syscall.RecvfromInet4(fd.Sysfd, p, 0, from)
244+
if err != nil {
245+
if err == syscall.EINTR {
246+
continue
247+
}
248+
n = 0
249+
if err == syscall.EAGAIN && fd.pd.pollable() {
250+
if err = fd.pd.waitRead(fd.isFile); err == nil {
251+
continue
252+
}
253+
}
254+
}
255+
err = fd.eofError(n, err)
256+
return n, err
257+
}
258+
}
259+
260+
// ReadFrom wraps the recvfrom network call for IPv6.
261+
func (fd *FD) ReadFromInet6(p []byte, from *syscall.SockaddrInet6) (int, error) {
262+
if err := fd.readLock(); err != nil {
263+
return 0, err
264+
}
265+
defer fd.readUnlock()
266+
if err := fd.pd.prepareRead(fd.isFile); err != nil {
267+
return 0, err
268+
}
269+
for {
270+
n, err := syscall.RecvfromInet6(fd.Sysfd, p, 0, from)
271+
if err != nil {
272+
if err == syscall.EINTR {
273+
continue
274+
}
275+
n = 0
276+
if err == syscall.EAGAIN && fd.pd.pollable() {
277+
if err = fd.pd.waitRead(fd.isFile); err == nil {
278+
continue
279+
}
280+
}
281+
}
282+
err = fd.eofError(n, err)
283+
return n, err
284+
}
285+
}
286+
233287
// ReadMsg wraps the recvmsg network call.
234288
func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
235289
if err := fd.readLock(); err != nil {

src/internal/poll/fd_windows.go

+18
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,24 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
593593
return n, sa, nil
594594
}
595595

596+
// ReadFrom wraps the recvfrom network call for IPv4.
597+
func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
598+
n, sa, err := fd.ReadFrom(buf)
599+
if sa != nil {
600+
*sa4 = *(sa.(*syscall.SockaddrInet4))
601+
}
602+
return n, err
603+
}
604+
605+
// ReadFrom wraps the recvfrom network call for IPv6.
606+
func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
607+
n, sa, err := fd.ReadFrom(buf)
608+
if sa != nil {
609+
*sa6 = *(sa.(*syscall.SockaddrInet6))
610+
}
611+
return n, err
612+
}
613+
596614
// Write implements io.Writer.
597615
func (fd *FD) Write(buf []byte) (int, error) {
598616
if err := fd.writeLock(); err != nil {

src/net/fd_posix.go

+11
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
6363
runtime.KeepAlive(fd)
6464
return n, sa, wrapSyscallError(readFromSyscallName, err)
6565
}
66+
func (fd *netFD) readFromInet4(p []byte, from *syscall.SockaddrInet4) (n int, err error) {
67+
n, err = fd.pfd.ReadFromInet4(p, from)
68+
runtime.KeepAlive(fd)
69+
return n, wrapSyscallError(readFromSyscallName, err)
70+
}
71+
72+
func (fd *netFD) readFromInet6(p []byte, from *syscall.SockaddrInet6) (n int, err error) {
73+
n, err = fd.pfd.ReadFromInet6(p, from)
74+
runtime.KeepAlive(fd)
75+
return n, wrapSyscallError(readFromSyscallName, err)
76+
}
6677

6778
func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {
6879
n, oobn, retflags, sa, err = fd.pfd.ReadMsg(p, oob, flags)

src/net/net_fake.go

+8
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,14 @@ func sysSocket(family, sotype, proto int) (int, error) {
266266

267267
func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
268268
return 0, nil, syscall.ENOSYS
269+
270+
}
271+
func (fd *netFD) readFromInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) {
272+
return 0, syscall.ENOSYS
273+
}
274+
275+
func (fd *netFD) readFromInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) {
276+
return 0, syscall.ENOSYS
269277
}
270278

271279
func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {

src/net/udpsock_posix.go

+19-7
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,25 @@ func (a *UDPAddr) toLocal(net string) sockaddr {
4444
}
4545

4646
func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) {
47-
n, sa, err := c.fd.readFrom(b)
48-
switch sa := sa.(type) {
49-
case *syscall.SockaddrInet4:
50-
*addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
51-
case *syscall.SockaddrInet6:
52-
*addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
53-
default:
47+
var n int
48+
var err error
49+
switch c.fd.family {
50+
case syscall.AF_INET:
51+
var from syscall.SockaddrInet4
52+
n, err = c.fd.readFromInet4(b, &from)
53+
if err == nil {
54+
ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 4 bytes
55+
*addr = UDPAddr{IP: ip[:], Port: from.Port}
56+
}
57+
case syscall.AF_INET6:
58+
var from syscall.SockaddrInet6
59+
n, err = c.fd.readFromInet6(b, &from)
60+
if err == nil {
61+
ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 16 bytes
62+
*addr = UDPAddr{IP: ip[:], Port: from.Port, Zone: zoneCache.name(int(from.ZoneId))}
63+
}
64+
}
65+
if err != nil {
5466
// No sockaddr, so don't return UDPAddr.
5567
addr = nil
5668
}

src/syscall/net_js.go

+8
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
9292
return 0, nil, ENOSYS
9393
}
9494

95+
func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) {
96+
return 0, ENOSYS
97+
}
98+
99+
func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) {
100+
return 0, ENOSYS
101+
}
102+
95103
func Sendto(fd int, p []byte, flags int, to Sockaddr) error {
96104
return ENOSYS
97105
}

src/syscall/syscall_unix.go

+27
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,33 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
292292
return
293293
}
294294

295+
func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) {
296+
var rsa RawSockaddrAny
297+
var socklen _Socklen = SizeofSockaddrAny
298+
if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil {
299+
return
300+
}
301+
pp := (*RawSockaddrInet4)(unsafe.Pointer(&rsa))
302+
port := (*[2]byte)(unsafe.Pointer(&pp.Port))
303+
from.Port = int(port[0])<<8 + int(port[1])
304+
from.Addr = pp.Addr
305+
return
306+
}
307+
308+
func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) {
309+
var rsa RawSockaddrAny
310+
var socklen _Socklen = SizeofSockaddrAny
311+
if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil {
312+
return
313+
}
314+
pp := (*RawSockaddrInet6)(unsafe.Pointer(&rsa))
315+
port := (*[2]byte)(unsafe.Pointer(&pp.Port))
316+
from.Port = int(port[0])<<8 + int(port[1])
317+
from.ZoneId = pp.Scope_id
318+
from.Addr = pp.Addr
319+
return
320+
}
321+
295322
func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) {
296323
ptr, n, err := to.sockaddr()
297324
if err != nil {

0 commit comments

Comments
 (0)