我写了一个简单的TCP服务器 问题在于,当对其进行压力测试时,内存使用量似乎会急剧增加,并且在测试完成时不会减少。 服务器启动时,需要大约700KB 在压力测试期间和之后,内存使用量跃升至~7MB 这是我的代码:
package main
import (
"net"
"log"
"fmt"
"bufio"
)
func main() {
ln, err := net.Listen("tcp", ":8888")
if err != nil {
log.Fatal(err)
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
continue
}
go handle(conn)
}
}
func handle(conn net.Conn) {
defer conn.Close()
fmt.Println("Accepted", conn.LocalAddr())
for {
buf, err := bufio.NewReader(conn).ReadString('\n')
if err != nil {
break
}
msg := string(buf[:len(buf)-2])
fmt.Println("Received", msg)
conn.Write([]byte("OK\n"))
}
}
非常感谢任何帮助。
注意:我使用tcpkali
加载它。这是命令行:
tcpkali -em "testing\r\n" -c 100 -r 1000 -T 60 127.0.0.1:8888
编辑:在下面的一些评论之后,我进行了一些测试,结果如下:
tcpkali
。tcpkali
,RSS爬升至8684. tcpkali
跑,RSS爬升到8696。tcpkali
跑,RSS爬升到8704。tcpkali
跑,RSS爬升到8712。现在,我不知道你称之为什么,但我称之为内存泄漏。这里不对劲。没有内存被释放,每次运行测试时RSS都会不断攀升。显然,这个东西不能部署到生产中,因为它最终将消耗所有可用的内存
我也尝试过调用os.FreeOSMemory()
但没有任何反应。
我的系统是macOS 10.13.1上的Go 1.9.4。这个环境是相关的还是我错过了什么?
最后更新:
在@Steffen Ullrich回答以及我的环境失败的测试之后,我试了一下Ubuntu服务器,并在几分钟的空闲时间后释放内存。
似乎macOS存在问题。
答案 0 :(得分:3)
Go不会立即释放从操作系统分配的内存。原因可能是分配内存成本高昂(需要系统调用),并且在不久的将来再次需要它的机会很高。但是,如果内存足够长,它将最终释放,以便进程的RSS再次降低。
稍微修改后再次进行测试会显示(至少对我来说):
请注意,并非所有内存都可以返回。根据{{3}},它不会返回(在1.3中)用于go例程堆栈的内存,因为将来更有可能需要这样做。
为了进行测试,您还可以在战略位置添加一些debug.FreeOSMemory()
(来自runtime/debug
)(例如当您在goroutine中退出循环时),以便先将内存返回到操作系统。但鉴于内存的懒惰回归是为了提高性能,这种显式释放可能会影响性能。