与许多goroutines一起消耗内存

时间:2014-03-11 13:12:03

标签: go concurrent-programming

我试图检查Go将如何使用100,000 goroutines。我写了一个简单的程序来产生许多例程,除了打印一些公告之外什么都不做。我将MaxStack大小限制为仅512字节。但我注意到程序大小并没有随之减少。它消耗了大约460 MB的内存,因此每个goroutine大约4 KB。我的问题是,我们可以设置最大堆栈大小低于"最小值" goroutines的堆栈大小(可能是4 KB)。我们如何设置Goroutine开始的最小堆栈大小? 以下是我用于测试的示例代码:

package main

import "fmt"
import "time"

import "runtime/debug"

func main() {
    fmt.Printf("%v\n", debug.SetMaxStack(512))
    var i int
    for i = 0; i < 100000; i++ {
        go func(x int) {
            for {
                time.Sleep(10 * time.Millisecond)
                //fmt.Printf("I am %v\n", x)
            }
        }(i)
    }
    fmt.Println("Done")
    time.Sleep(999999999999)
}

3 个答案:

答案 0 :(得分:8)

目前无法为goroutines设置最小堆栈大小。

Go 1.2将最小尺寸从4KB增加到8KB

The docs说:

  

“在Go 1.2中,创建goroutine时堆栈的最小大小已从4KB提升到8KB。许多程序都遇到了旧版本的性能问题,这有可能引入昂贵的堆栈段切换性能关键部分。新数字是通过实证测试确定的。“

但他们继续说:

  

“更新:增加的最小堆栈大小可能会导致具有许多goroutine的程序使用更多内存。没有解决方法,但未来版本的计划包括应该更好地解决问题的新堆栈管理技术。”

所以你将来可能会有更多的运气。

有关详细信息,请参阅http://golang.org/doc/go1.2#stack_size

答案 1 :(得分:7)

运行时/ debug.SetMaxStack函数只确定程序无限递归的点,并终止它。 http://golang.org/pkg/runtime/debug/#SetMaxStack

将其设置为荒谬的低对堆栈的最小大小没有任何影响,并且只有当任何堆栈的使用中大小超过限制时程序崩溃时才会限制最大大小。

从技术上讲,崩溃只发生在必须增加堆栈时,所以当堆栈需要超过8KB(或者在1.2之前的4KB)时,程序将会死亡。

您的程序使用至少4KB * nGoroutine的原因是因为堆栈是页面对齐的,因此VM页面上永远不会有多个堆栈。因此,您的程序将使用至少nGoroutines值的页面,并且操作系统通常仅以页面大小的增量来测量和分配内存。

更改堆栈的起始(最小)大小的唯一方法是修改和重新编译go运行时(也可能是编译器)。

Go 1.3将包含连续堆栈,这些堆栈通常比Go 1.2及更早版本中的拆分堆栈更快,并且可能导致将来更小的初始堆栈。

答案 2 :(得分:0)

请注意::在Go 1.4中:goroutine堆栈的最小大小已从8Kb减小到2Kb。

根据Go 1.13,它仍然相同-https://github.com/golang/go/blob/bbd25d26c0a86660fb3968137f16e74837b7a9c6/src/runtime/stack.go#L72

// The minimum size of stack used by Go code
_StackMin = 2048