请问这段 Go 代码会内存泄漏吗?

2018-12-06 18:24:09 +08:00
 petelin

import (
   "fmt"
   "runtime"
   "strconv"
   "time"
)

func do() {
   max := 2100000
   item := 11511
   var a []int
   for range make([]struct{}, max) {
      a = append(a, item)
   }
   var sitem []string
   for range make([]struct{}, max) {
      sitem = append(sitem, strconv.Itoa(item))
   }
   fmt.Println(len(sitem))
   runtime.GC()
}

func main() {
   for range make([]struct{}, 10) {
      go do()
   }
   time.Sleep(time.Hour)
}``` 我个逻辑线上的代码简化版,占用内存 1.1G...怎么会这样, 是没有被 GC 掉吗?
3709 次点击
所在节点    Go 编程语言
13 条回复
xujiaja
2018-12-06 18:58:13 +08:00
如果想要立即释放,可以调用 runtime/debug 里的 FreeOSMemory()
petelin
2018-12-06 20:57:56 +08:00
@xujiaja em...也试了, 内存也没有减少
Licsber
2018-12-06 21:12:56 +08:00
试了一下, 占用内存从 1000M 在 5 秒左右掉到了 744M 10 秒左右 434M 15 秒左右 239M 20 秒就只有 99M 了 最后稳定在 3M 内存占用 没发现 gc 失败啊.. go 最新版本 1.11.2 goland 也是最新版本 2018.3
petelin
2018-12-06 21:24:31 +08:00
@Licsber 请问你用什么工具看内存的? 我对 htop 是不是有点误解...
petelin
2018-12-06 21:37:19 +08:00
@Licsber 我在 mac 上测试的, 好像是因为 thread 没有退出.
Sampling process 19768 for 3 seconds with 1 millisecond of run time between samples
Sampling completed, processing symbols...
Analysis of sampling ___go_build_add_go (pid 19768) every 1 millisecond
Process: ___go_build_add_go [19768]
Path: /private/var/folders/wd/vt73dmmj5y38hft8kg5l1wgm0000gq/T/___go_build_add_go
Load Address: 0x1000000
Identifier: ___go_build_add_go
Version: ???
Code Type: X86-64
Parent Process: goland [14064]

Date/Time: 2018-12-06 21:33:47.174 +0800
Launch Time: 2018-12-06 21:33:00.224 +0800
OS Version: Mac OS X 10.13.6 (17G3025)
Report Version: 7
Analysis Tool: /usr/bin/sample

Physical footprint: 1.2G
Physical footprint (peak): 1.2G
----

Call graph:
2580 Thread_15197711 DispatchQueue_1: com.apple.main-thread (serial)
+ 2580 runtime.asmcgocall (in ___go_build_add_go) + 112 [0x1050da0]
+ 2580 runtime.pthread_cond_timedwait_relative_np_trampoline (in ___go_build_add_go) + 20 [0x1053204]
+ 2580 _pthread_cond_wait (in libsystem_pthread.dylib) + 789 [0x7fff5779a5c2]
+ 2580 __psynch_cvwait (in libsystem_kernel.dylib) + 10 [0x7fff575d1a16]
2580 Thread_15197713
+ 2580 thread_start (in libsystem_pthread.dylib) + 13 [0x7fff57798bf9]
+ 2580 _pthread_start (in libsystem_pthread.dylib) + 377 [0x7fff5779950d]
+ 2580 runtime.mstart_stub (in ___go_build_add_go) + 46 [0x10530ce]
+ 2580 runtime.mstart (in ___go_build_add_go) + 102 [0x102b9d6]
+ 2580 runtime.mstart1 (in ___go_build_add_go) + 230 [0x102bad6]
+ 2580 runtime.sysmon (in ___go_build_add_go) + 371 [0x10330b3]
+ 2580 runtime.notetsleep (in ___go_build_add_go) + 105 [0x1009499]
+ 2580 runtime.notetsleep_internal (in ___go_build_add_go) + 269 [0x10092cd]
+ 2580 runtime.semasleep (in ___go_build_add_go) + 271 [0x1024e3f]
+ 2580 runtime.pthread_cond_timedwait_relative_np (in ___go_build_add_go) + 81 [0x1043301]
+ 2580 runtime.asmcgocall (in ___go_build_add_go) + 173 [0x1050ddd]
+ 2580 runtime.pthread_cond_timedwait_relative_np_trampoline (in ___go_build_add_go) + 20 [0x1053204]
+ 2580 _pthread_cond_wait (in libsystem_pthread.dylib) + 789 [0x7fff5779a5c2]
+ 2580 __psynch_cvwait (in libsystem_kernel.dylib) + 10 [0x7fff575d1a16]
2580 Thread_15197714
+ 2580 runtime.mcall (in ___go_build_add_go) + 91 [0x104f52b]
+ 2580 runtime.goexit0 (in ___go_build_add_go) + 498 [0x102f552]
+ 2580 runtime.schedule (in ___go_build_add_go) + 314 [0x102eb6a]
+ 2580 runtime.findrunnable (in ___go_build_add_go) + 1244 [0x102e05c]
+ 2580 runtime.stopm (in ___go_build_add_go) + 227 [0x102cee3]
+ 2580 runtime.notesleep (in ___go_build_add_go) + 227 [0x1009163]
+ 2580 runtime.semasleep (in ___go_build_add_go) + 133 [0x1024db5]
+ 2580 runtime.pthread_cond_wait (in ___go_build_add_go) + 81 [0x1043291]
+ 2580 runtime.asmcgocall (in ___go_build_add_go) + 173 [0x1050ddd]
+ 2580 runtime.pthread_cond_wait_trampoline (in ___go_build_add_go) + 16 [0x10531e0]
+ 2580 _pthread_cond_wait (in libsystem_pthread.dylib) + 732 [0x7fff5779a589]
+ 2580 __psynch_cvwait (in libsystem_kernel.dylib) + 10 [0x7fff575d1a16]
.... 一共重复了 10 个 thread. 我在研究一下
petelin
2018-12-06 21:40:24 +08:00
@petelin 巧合, 里面的内容和我的业务逻辑没关系...
xujiaja
2018-12-06 21:52:26 +08:00
我在 main 函数里面的循环 sleep,一秒创建一个协程的情况下,内存基本上稳定在第一次协程分配的值。应该是主程序 sleep 的情况下,并没有其他的对象要分配,所以就不回收了。
petelin
2018-12-07 10:50:10 +08:00
@xujiaja 你是对的, 我把最后那个 sleep 一个小时, 改成了 for{}, 就可以回收了. 谢谢
HanMeiM
2018-12-07 10:50:30 +08:00
- -我也基本上维持在 1 - 1.1g 左右的内存占用
Vegetable
2018-12-07 10:53:42 +08:00
测了一下你的代码,稳定一会儿 1.2g,后来忘记看了,过了十来分钟看一下 50M 了.
Licsber
2018-12-07 21:12:52 +08:00
@petelin 就是 htop 啊 稍微过一会就能看到内存急剧下降 2018 款 MacBookpro 系统是最新的 Mojave 和我的环境应该没啥问题吧..
petelin
2018-12-08 11:20:21 +08:00
@Licsber 感觉和环境真有关系,你确定一模一样?包括 time.sleep ?
Licsber
2018-12-08 16:06:26 +08:00
@petelin 对的 我一行代码都没改 直接 go build 运行的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/515068

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX