【问题标题】:Why simple Go app consume high memory usage为什么简单的 Go 应用程序会消耗大量内存
【发布时间】:2019-08-05 13:44:05
【问题描述】:

这是一个非常简单的应用程序:

package main
import "fmt"
func main() {

    for i:= 0; i < 100000; i++ {
        go func (){
            fmt.Println("hello message.")
        }()
    }

    fmt.Scanln()
    fmt.Println("done")
}

在 windows 上运行应用程序后,查看 windows 任务管理器我看到了这种状态:

有人能说出为什么吗?

【问题讨论】:

  • 为什么你认为884mb是高内存使用?我想说这对于多达 10 万个 goroutine 来说是相当令人印象深刻的。
  • 因为我使用 .NET Core 使用 Tasks 模拟了这个程序,它只消耗了 17 MB 的内存!
  • 如何在 .NET 中“模拟”goroutine?
  • @RahmatAnjirabi 如果您还确保您的 .NET 解决方案在启动所有 100,000 个线程之前也没有结束任何线程,您只能比较内存使用情况。
  • 从 GopherCon 查看The Scheduler Saga。它深入解释了 Go 调度器:about.sourcegraph.com/go/gophercon-2018-the-scheduler-saga

标签: string go memory-leaks goroutine


【解决方案1】:

启动的 goroutines 并发运行,彼此独立。处理它们是 goroutine 调度器的责任和义务。

goroutine 是一个轻量级线程:它的成本比 OS 线程低很多,但仍然需要一些成本。一个新的 goroutine 的初始堆栈是几个 KB(大约 8KB),并根据需要增长/缩小。见Goroutines 8kb and windows OS thread 1 mb

假设您在没有任何同步的情况下启动了 100,000 个 goroutine,那么您很可能会在其中任何一个完成之前运行 100,000 个 goroutine。估计的内存需求为:

100,000 * 8KB = 800 MB

因此,您的应用使用 884MB 与估计值非常吻合。

【讨论】:

  • 那为什么我删除 fmt.Println 行时不会占用更多内存?
  • @RahmatAnjirabi 如果你从 goroutine 中删除 fmt.Pritnln() 调用,函数体实际上会变空,并且这些 goroutine 会在你检查内存使用之前更快地完成。编译器甚至可能完全优化这些 goroutine 启动。
  • @RahmatAnjirabi 使用的内存不会立即释放回操作系统。见Cannot free memory once occupied by bytes.Buffer
猜你喜欢
  • 1970-01-01
  • 2011-05-10
  • 1970-01-01
  • 1970-01-01
  • 2016-06-30
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
相关资源
最近更新 更多