Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory 当声明非常大的数组并在stdin上迭代时,连续内存会增加_Memory_Go - Fatal编程技术网

Memory 当声明非常大的数组并在stdin上迭代时,连续内存会增加

Memory 当声明非常大的数组并在stdin上迭代时,连续内存会增加,memory,go,Memory,Go,下面的代码声明了两个数组,然后在stdin上迭代(只是盲目地在文件上迭代-与数组没有交互) 这会导致内存不断增加 然而,如果我只声明两个数组和sleep,内存不会增加 类似地,如果我只是在stdin上迭代-内存没有增加 但总的来说(除了为阵列分配的内存之外)会不断增加 我通过使用top工具查看RES内存来测量这一点 我已经注释掉了func doSomething()中的前几行,以表明在注释时没有内存增加。取消对行的注释并运行将导致增加 注:这是在go 1.4.2、1.5.3和1.6上运行的 注意

下面的代码声明了两个数组,然后在stdin上迭代(只是盲目地在文件上迭代-与数组没有交互)

这会导致内存不断增加

然而,如果我只声明两个数组和sleep,内存不会增加

类似地,如果我只是在stdin上迭代-内存没有增加

但总的来说(除了为阵列分配的内存之外)会不断增加

我通过使用top工具查看RES内存来测量这一点

我已经注释掉了
func doSomething()
中的前几行,以表明在注释时没有内存增加。取消对行的注释并运行将导致增加

注:这是在go 1.4.2、1.5.3和1.6上运行的

注意:您将需要在至少有16GB RAM的机器上重新创建它,因为我只在10亿大小的阵列上观察到了这一点

主程序包
进口(
“布菲奥”
“fmt”
“io”
“操作系统”
)
类型MyStruct struct{
arr1[]整数
arr2[]整数
}
func(ms*MyStruct)Init(size int,arr1[]int,arr2[]int)错误{
fmt.Printf(“初始化mystruct arr1…\n”)
ms.arr1=arr1
如果ms.arr1==nil{
ms.arr1=make([]整数,大小,大小)
}
fmt.Printf(“初始化mystruct arr2…\n”)
ms.arr2=arr2
如果ms.arr2==nil{
ms.arr2=make([]整数,大小,大小)
}
fmt.Printf(“完成初始化…\n”)
对于i:=0;i
  • 这是我的代码的问题吗?还是围棋系统做了一些意想不到的事情
  • 如果是后者,我如何进行调试
  • 为了便于复制,这里提供了用于良好案例(上面代码的注释部分)和不良案例(未注释部分)的pastebin文件

    wgethttp://pastebin.com/raw/QfG22xXk -哦,坏家伙,走
    是“1234567890”|快跑坏箱子。快跑
    wgethttp://pastebin.com/raw/G9xS2fKy -哦,古德凯斯,走吧
    是“1234567890”|开始运行goodcase.go
    
    感谢您的上述评论。我想捕捉调试这个的过程作为一个答案

    RES
    top/htop
    只是在进程级别告诉您内存中发生了什么。GODEBUG=“gctrace=1”可以让您更深入地了解内存的处理方式

    使用gctrace集进行简单的运行可以得到以下结果

    root@localhost ~ # yes "12345678901234567890123456789012" | GODEBUG="gctrace=1" go run badcase.go
    starting...
    allocating
    initializing mystruct arr1...
    initializing mystruct arr2...
    gc 1 @0.050s 0%: 0.19+0.23+0.068 ms clock, 0.58+0.016/0.16/0.25+0.20 ms cpu, 7629->7629->7629 MB, 7630 MB goal, 8 P
    done initializing ...
    gc 2 @0.100s 0%: 0.070+2515+0.23 ms clock, 0.49+0.025/0.096/0.24+1.6finished allocating..1000000000 1000000000
     ms cpu, 15258->15258reading from stdin...
    ->15258 MB, 15259read 0 lines...
     MB goal, 8 P
    gc 3 @2.620s 0%: 0.009+0.32+0.23 ms clock, 0.072+0/0.20/0.11+1.8 ms cpu, 15259->15259->15258 MB, 30517 MB goal, 8 P
    
    read 1000000 lines...
    read 2000000 lines...
    read 3000000 lines...
    read 4000000 lines...
    ....
    read 51000000 lines...
    read 52000000 lines...
    read 53000000 lines...
    read 54000000 lines...
    
    这是什么意思

    如您所见,gc已经有一段时间没有被调用了。这意味着从reader.ReadString生成的所有垃圾尚未收集和释放

    为什么垃圾收集器不收集这些垃圾

    相反,我们提供了一个单独的旋钮,称为GOGC。此值控制 相对于可访问对象的大小,堆的总大小。 默认值100意味着堆的总大小现在增加了100% 大于(即,两倍)最后一次之后可到达对象的大小 收藏

    由于未设置GOGC,默认值为100%。因此,它只有在达到~32GB时才会收集垃圾。(因为最初这两个数组为您提供16GB的堆空间-只有当堆加倍时,gc才会触发)

    我怎样才能改变这个? 尝试将GOGC设置为25

    以GOGC为25

    root@localhost ~ # yes "12345678901234567890123456789012" | GODEBUG="gctrace=1" GOGC=25 go run badcase.go
    starting...
    allocating
    initializing mystruct arr1...
    initializing mystruct arr2...
    gc 1 @0.051s 0%: 0.14+0.30+0.11 ms clock, 0.42+0.016/0.31/0.094+0.35 ms cpu, 7629->7629->7629 MB, 7630 MB goal, 8 P
    done initializing ...
    finished allocating..1000000000 1000000000
    gc 2 @0.102s reading from stdin...
    12%: 0.058+2480+0.26 ms clock, 0.40+0.022/2480/0.10+1.8 ms cpu, 15258->15258->15258 MB, 15259 MB goal, 8 P
    read 0 lines...
    gc 3 @2.584s 12%: 0.009+0.20+0.22 ms clock, 0.075+0/0.24/0.046+1.8 ms cpu, 15259->15259->15258 MB, 19073 MB goal, 8 P
    read 1000000 lines...
    read 2000000 lines...
    read 3000000 lines...
    read 4000000 lines...
    ....
    read 19000000 lines...
    read 20000000 lines...
    gc 4 @6.539s 4%: 0.019+2.3+0.23 ms clock, 0.15+0/2.1/12+1.8 ms cpu, 17166->17166->15258 MB, 19073 MB goal, 8 P
    
    如您所见,触发了另一个gc

    但top/htop显示其稳定在约20GB,而不是计算的16GB


    垃圾收集器“不必”将其返回操作系统。它有时会保留它以便将来有效地使用。它不必不断地从操作系统中获取和回馈—在再次询问操作系统之前,额外的4 gb空间就在其可用空间池中。

    如何衡量“内存增加”以及您所谈论的内存类型。很可能一切都很好;略读你的代码看起来没问题。当然,如果分配20亿个整数,代码将消耗更多内存,因为这至少是8GB。@Volker我启动了一个htop并监视RES内存。是的,在64位机器上,启动时大约需要16GB,但当我开始从stdin读取数据时,它就会迅速上升,并且永不停止。(更新问题以反映评论)。你确定它真的不会停止吗?要了解记忆,请特别关注GODEBUG和gctrace,这比(h)更有帮助top@Volker只是确认一下——这个过程中RES的持续增加确定了内存正在增加的事实。我将不得不使用godebug和gctrace来找出原因,对吗?另外,“并没有真正停止”是我假设的,当它从16(它应该是什么)增加到32 Gig(我的ram限制)之后,它进入了交换,所以我杀死了它。要查看操作系统htop提供给它的内存发生了什么以及Go做了什么是不够的。使用GODEBUG=“gctrace=1”查看Go的垃圾收集器的“内部”。您可能会发现GC没有“足够频繁地”运行:这是