我的操作系统环境是MacOS 10.14
我的golang环境是go版本go1.11 darwin / amd64
这是我的简化代码:
import (
_ "net/http/pprof"
)
var (
wg sync.WaitGroup
)
func main() {
go func() {
http.ListenAndServe(":6060", nil)
}()
ticker := time.NewTicker(time.Millisecond * 300)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
for {
select {
case <-ticker.C:
doBan()
case <-c:
goto DONE
}
}
DONE:
doBan()
wg.Wait()
}
func doBan() {
for i := 0; i < 4; i++ {
wg.Add(1)
ips := getIps(i)
go banIps(ips)
}
}
func banIps(ips []string) {
ipset := exec.Command("ipset", "-!", "restore")
r, w := io.Pipe()
ipset.Stdin = r
if err := ipset.Start(); err != nil {
w.Close()
} else {
for _, ip := range (ips) {
fmt.Fprintf(w, "add ipset %s timeout 3600\n", ip)
}
w.Close()
}
defer ipset.Wait()
defer wg.Done()
}
// get lots of ips in real world
func getIps(i int) []string {
ip := fmt.Sprintf("%d.%d.%d.%d", i, i, i, i)
return []string{ip}
}
然后我使用go工具pprof来监视内存信息。
http://localhost:6060/debug/pprof/heap?debug=1
的结果是这样的:
heap profile: 0: 0 [124: 41696] @ heap/1048576 0: 0 [1: 32] @ 0x10e96b6 0x10e5a67 0x13095a5 0x105d0d1
# 0x10e96b5 os/exec.LookPath+0x1a5 /usr/local/Cellar/go/1.11/libexec/src/os/exec/lp_unix.go:57
# 0x10e5a66 os/exec.Command+0x1b6 /usr/local/Cellar/go/1.11/libexec/src/os/exec/exec.go:161
# 0x13095a4 main.banIps+0x84 /Users/kiyon/Code/github/go/src/github.com/kiyonlin/hello- application/testcmd/main.go:50
0: 0 [3: 96] @ 0x1047d8f 0x104786d 0x1047b07 0x10e0e13 0x10e5657 0x10e53ef 0x10e9662 0x10e5a67 0x13095a5 0x105d0d1
# 0x10e0e12 strings.Join+0x452 /usr/local/Cellar/go/1.11/libexec/src/strings/strings.go:429
# 0x10e5656 path/filepath.join+0xa6 /usr/local/Cellar/go/1.11/libexec/src/path/filepath/path_unix.go:45
# 0x10e53ee path/filepath.Join+0x3e /usr/local/Cellar/go/1.11/libexec/src/path/filepath/path.go:210
# 0x10e9661 os/exec.LookPath+0x151 /usr/local/Cellar/go/1.11/libexec/src/os/exec/lp_unix.go:52
# 0x10e5a66 os/exec.Command+0x1b6 /usr/local/Cellar/go/1.11/libexec/src/os/exec/exec.go:161
# 0x13095a4 main.banIps+0x84 /Users/kiyon/Code/github/go/src/github.com/kiyonlin/hello-application/testcmd/main.go:50
0: 0 [2: 32] @ 0x1068c56 0x1068d19 0x106e4f9 0x109c93c 0x109c40d 0x10e9489 0x10e9684 0x10e5a67 0x13095a5 0x105d0d1
# 0x1068c55 syscall.ByteSliceFromString+0x95 /usr/local/Cellar/go/1.11/libexec/src/syscall/syscall.go:53
# 0x1068d18 syscall.BytePtrFromString+0x38 /usr/local/Cellar/go/1.11/libexec/src/syscall/syscall.go:69
# 0x106e4f8 syscall.Stat+0x38 /usr/local/Cellar/go/1.11/libexec/src/syscall/zsyscall_darwin_amd64.go:1188
# 0x109c93b os.statNolog+0x5b /usr/local/Cellar/go/1.11/libexec/src/os/stat_unix.go:31
# 0x109c40c os.Stat+0x4c /usr/local/Cellar/go/1.11/libexec/src/os/stat.go:13
# 0x10e9488 os/exec.findExecutable+0x38 /usr/local/Cellar/go/1.11/libexec/src/os/exec/lp_unix.go:20
# 0x10e9683 os/exec.LookPath+0x173 /usr/local/Cellar/go/1.11/libexec/src/os/exec/lp_unix.go:53
# 0x10e5a66 os/exec.Command+0x1b6 /usr/local/Cellar/go/1.11/libexec/src/os/exec/exec.go:161
# 0x13095a4 main.banIps+0x84 /Users/kiyon/Code/github/go/src/github.com/kiyonlin/hello-application/testcmd/main.go:50
0: 0 [2: 192] @ 0x13095ee 0x105d0d1
# 0x13095ed io.Pipe+0xcd /usr/local/Cellar/go/1.11/libexec/src/io/pipe.go:189
# 0x13095ed main.banIps+0xcd /Users/kiyon/Code/github/go/src/github.com/kiyonlin/hello-application/testcmd/main.go:51
......
我可以看到pprof中的heap
个人资料随时间增长。
这意味着在调用exec.Command
和io.Pipe()
函数之后,我还没有释放一些内存。
我不知道我的代码有什么问题。
谢谢大家!