Skip to content

Commit 312ac47

Browse files
committed
[tailscale1.16] 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 17c11ce commit 312ac47

File tree

8 files changed

+199
-6
lines changed

8 files changed

+199
-6
lines changed

api/go1.tailscale.txt

Lines changed: 52 additions & 0 deletions
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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,60 @@ func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) {
229229
}
230230
}
231231

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

src/internal/poll/fd_windows.go

Lines changed: 18 additions & 0 deletions
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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
6262
runtime.KeepAlive(fd)
6363
return n, sa, wrapSyscallError(readFromSyscallName, err)
6464
}
65+
func (fd *netFD) readFromInet4(p []byte, from *syscall.SockaddrInet4) (n int, err error) {
66+
n, err = fd.pfd.ReadFromInet4(p, from)
67+
runtime.KeepAlive(fd)
68+
return n, wrapSyscallError(readFromSyscallName, err)
69+
}
70+
71+
func (fd *netFD) readFromInet6(p []byte, from *syscall.SockaddrInet6) (n int, err error) {
72+
n, err = fd.pfd.ReadFromInet6(p, from)
73+
runtime.KeepAlive(fd)
74+
return n, wrapSyscallError(readFromSyscallName, err)
75+
}
6576

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

src/net/net_fake.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,14 @@ func sysSocket(family, sotype, proto int) (int, error) {
265265

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

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

src/net/udpsock_posix.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,27 @@ func (a *UDPAddr) toLocal(net string) sockaddr {
4343
}
4444

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

src/syscall/net_js.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
9191
return 0, nil, ENOSYS
9292
}
9393

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

src/syscall/syscall_unix.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,33 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
290290
return
291291
}
292292

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

0 commit comments

Comments
 (0)