Description
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (go version
)?
go version go1.10.3 linux/amd64
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (go env
)?
GOARCH="amd64"
GOOS="linux"
What did you do?
I use writev to write buffer into tcpconn. in order to reduce gc, I try to reuse object as far as possible.
and i did it so. but when i run go tool pprof to analysis of the memory。I found Writev alloc memory every time is called.
0: 0 [2990: 95680] @ 0x49225f 0x58df7b 0x58dd76 0x57ebe7 0x77232f 0x773aad 0x784329 0x79d09b 0x7a0958 0x45a851
# 0x49225e internal/poll.(*FD).Writev+0xde /usr/local/Cellar/go/1.10/libexec/src/internal/poll/writev.go:25
# 0x58df7a net.(*netFD).writeBuffers+0x3a /usr/local/Cellar/go/1.10/libexec/src/net/writev_unix.go:26
# 0x58dd75 net.(*conn).writeBuffers+0x55 /usr/local/Cellar/go/1.10/libexec/src/net/writev_unix.go:18
# 0x57ebe6 net.(*Buffers).WriteTo+0x1a6 /usr/local/Cellar/go/1.10/libexec/src/net/net.go:638
# 0x77232e overlord/lib/net.(*Conn).Writev+0x6e /work/go/src/overlord/lib/net/conn.go:115
# 0x773aac overlord/lib/bufio.(*Writer).Flush+0x8c /work/go/src/overlord/lib/bufio/io.go:174
1: 256 [1: 256] @ 0x492616 0x58df7b 0x58dd76 0x57ebe7 0x77232f 0x773aad 0x784329 0x79d09b 0x7a0958 0x45a851
# 0x492615 internal/poll.(*FD).Writev+0x495 /usr/local/Cellar/go/1.10/libexec/src/internal/poll/writev.go:42
# 0x58df7a net.(*netFD).writeBuffers+0x3a /usr/local/Cellar/go/1.10/libexec/src/net/writev_unix.go:26
# 0x58dd75 net.(*conn).writeBuffers+0x55 /usr/local/Cellar/go/1.10/libexec/src/net/writev_unix.go:18
# 0x57ebe6 net.(*Buffers).WriteTo+0x1a6 /usr/local/Cellar/go/1.10/libexec/src/net/net.go:638
# 0x77232e overlord/lib/net.(*Conn).Writev+0x6e /work/go/src/overlord/lib/net/conn.go:115
# 0x773aac overlord/lib/bufio.(*Writer).Flush+0x8c /work/go/src/overlord/lib/bufio/io.go:174
and the go tool pprof show:
$go tool pprof -alloc_space http://127.0.0.1:2110/debug/pprof/heap
(pprof) cum
(pprof) top
Showing nodes accounting for 303.01MB, 91.27% of 331.99MB total
Dropped 51 nodes (cum <= 1.66MB)
Showing top 10 nodes out of 24
flat flat% sum% cum cum%
302.51MB 91.12% 91.12% 302.51MB 91.12% internal/poll.(*FD).Writev
0 0% 91.12% 302.51MB 91.12% net.(*Buffers).WriteTo
0 0% 91.12% 302.51MB 91.12% net.(*conn).writeBuffers
0 0% 91.12% 302.51MB 91.12% net.(*netFD).writeBuffers
0 0% 91.12% 302.51MB 91.12% overlord/lib/bufio.(*Writer).Flush
0 0% 91.12% 302.51MB 91.12% overlord/lib/net.(*Conn).Writev
0 0% 91.12% 170.02MB 51.21% overlord/proxy.(*Handler).handle
as pprof showed. almost all memory was alloced by Writev
analysis of the object escape
./writev.go:16:43: leaking param: fd
./writev.go:16:43: from fd (passed to call[argument escapes]) at ./writev.go:17:24
./writev.go:42:48: &chunk[0] escapes to heap
./writev.go:42:48: from syscall.Iovec literal (struct literal element) at ./writev.go:42:41
./writev.go:42:48: from append(iovecs, syscall.Iovec literal) (appended to slice) at ./writev.go:42:19
./writev.go:16:43: leaking param content: v
./writev.go:16:43: from *v (indirection) at ./writev.go:38:25
./writev.go:16:43: from * (*v) (indirection) at ./writev.go:38:25
./writev.go:16:43: from chunk (range-deref) at ./writev.go:38:19
./writev.go:16:43: from chunk[0] (dot of pointer) at ./writev.go:42:54
./writev.go:16:43: from &chunk[0] (address-of) at ./writev.go:42:48
./writev.go:16:43: from syscall.Iovec literal (struct literal element) at ./writev.go:42:41
./writev.go:16:43: from append(iovecs, syscall.Iovec literal) (appended to slice) at ./writev.go:42:19
./writev.go:55:15: &iovecs escapes to heap
./writev.go:55:15: from fd.iovecs (star-dot-equals) at ./writev.go:55:13
./writev.go:25:6: moved to heap: iovecs
./writev.go:72:8: syscall.Errno(e0) escapes to heap
./writev.go:72:8: from err (assigned) at ./writev.go:72:8
./writev.go:72:8: from ~r2 (return) at ./writev.go:82:2
./writev.go:21:17: (*FD).Writev fd.pd does not escape
./writev.go:44:26: (*FD).Writev iovecs[len(iovecs) - 1] does not escape
./writev.go:47:25: (*FD).Writev iovecs[len(iovecs) - 1] does not escape
./writev.go:59:27: (*FD).Writev &iovecs[0] does not escape
./writev.go:68:18: (*FD).Writev fd.pd does not escape
At line42 it show &chunk[0] is escapes to heap.and in pprof it alloc mem every time.
it is that possilbe to make noescape to avoid obj alloc in heap or reuse these obj to avoid gc?
What did you expect to see?
the iovec object should be alloced in stack in oder to avoid gc, but it escaped to heap.
What did you see instead?
iovec was escape to heap and alloc mem every time and made gc frequently.