Go 程序的主 Goroutine 和衍生 Goroutine 之间的区别

2023-11-29

创建服务器时使用gRPC,如果我开始gRPC服务器在主进程中,它可以处理来自客户端的请求(数千个)。但是,如果我将服务器作为 goroutine 启动,它只能处理一些请求(数百个),然后就会卡住。我已经用一个非常简单的示例 google.golang.org/grpc/examples/helloworld 测试并确认了这一点。

是因为生成的 goroutine 堆栈大小非常小(2Kbytes),而主 goroutine 却大得多吗?主 Goroutine 和衍生 Goroutine 有什么区别?

Example link。示例的部分修改如下。

迎宾服务器/main.go

func main() {
    go func() {
        lis, err := net.Listen("tcp", port)
        if err != nil {
            log.Fatalf("failed to listen: %v", err)
        }   
        s := grpc.NewServer()
        pb.RegisterGreeterServer(s, &server{})
        s.Serve(lis)
    }() 

    for {
    }   
}

迎宾客户端/main.go

func main() {
    // Set up a connection to the server.
    for i := 0; i < 500; i++ {
        conn, err := grpc.Dial(address, grpc.WithInsecure())
        if err != nil {
            log.Fatalf("did not connect: %v", err)
        }
        defer conn.Close()
        c := pb.NewGreeterClient(conn)

        for i := 0; i < 500; i++ {
            // Contact the server and print out its response.
            name := defaultName
            if len(os.Args) > 1 {
                name = os.Args[1]
            }
            r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
            if err != nil {
                log.Fatalf("could not greet: %v", err)
            }
            log.Printf("%d's Greeting: %s", i, r.Message)
        }
    }
}

为什么 Goroutine 的堆栈是无限的:

Goroutine 的主要特征之一是它们的成本;他们很便宜 根据初始内存占用量创建(而不是 1 到 8 兆字节(传统的 POSIX 线程)并且它们的堆栈增长并且 根据需要收缩。这允许 Goroutine 以单个 4096 字节堆栈,可根据需要增长和缩小,而不会出现以下风险 永远用完。

然而,直到现在我还没有透露一个细节,它与 意外使用递归函数造成严重内存占用 操作系统耗尽,也就是说,当新堆栈 需要页面,它们是从堆中分配的。

当你的无限函数继续调用自身时,新的堆栈页面 从堆中分配,允许函数继续 一遍又一遍地调用自己。很快堆的大小 将超过您计算机中的可用物理内存量 哪个点交换很快就会使您的机器无法使用。

Go 程序可用的堆大小取决于很多因素 事物,包括 CPU 的架构和操作 系统,但它通常表示超过的内存量 你机器的物理内存,所以你的机器很可能会交换 在你的程序耗尽它的堆之前就大量地加载。

ref: http://dave.cheney.net/2013/06/02/why-is-a-goroutines-stack-infinite


空循环:

for{
}

使用 100% 的 CPU 核心,等待某些操作,具体取决于您可能使用的用例:
- sync.WaitGroup like this
- select {} like this
- 频道
- time.Sleep


是因为生成的 goroutine 堆栈大小非常小(2Kbytes), 主 Goroutine 更大吗?

不,你可以尝试这两个示例,看看 goroutine 的堆栈限制是相同的:
一个主 goroutine围棋游乐场,
尝试第二个 goroutine围棋游乐场:

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {
    wg.Add(1)
    go run()
    wg.Wait()
}
func run() {
    s := &S{a: 1, b: 2}
    fmt.Println(s)
    wg.Done()
}

type S struct {
    a, b int
}

// String implements the fmt.Stringer interface
func (s *S) String() string {
    return fmt.Sprintf("%s", s) // Sprintf will call s.String()
}

Go Playground 上的两个输出是相同的:

runtime: goroutine stack exceeds 250_000_000-byte limit
fatal error: stack overflow

在 PC 上输出8 GB RAM:

runtime: goroutine stack exceeds 1_000_000_000-byte limit
fatal error: stack overflow
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go 程序的主 Goroutine 和衍生 Goroutine 之间的区别 的相关文章

  • Go 中的 WebP 编码器/解码器

    是否有一个完整的 WebP 编码器和解码器与当前每周 或可分叉 兼容 它的速度与标准 png 相当吗 这个人在 GitHub 上有一个包 其中包含 WebP 的编码器和解码器 https github com chai2010 webp h
  • Go 无法推断赋值中的类型:“non-name on left side of :=”

    该片段按预期工作play golang org p VuCl OKMav http play golang org p VuCl OKMav i 10 next 11 prev i i next 然而这个几乎相同的片段给出了non name
  • Gorm 总是返回带有 nil 值的结构

    我正在使用 Gorm 构建 Go Web API 作为 Amazon RDS 中 Postgresql 数据库的 ORM 问题是 Gorm 总是返回一片结构 其值全部为零 尽管数据库已经填充了数据 切片中的结构体数量是否合适取决于LIMIT
  • Golang中如何删除字符串的最后一个字符?

    我想删除字符串的最后一个字符 但在此之前我想检查最后一个字符是否是 如何才能做到这一点 以下是删除尾随加号的几种方法 package main import fmt strings func TrimSuffix s suffix stri
  • 编写每个处理程序中间件

    我希望从处理程序中提取一些重复的逻辑 并将其放入一些每个处理程序的中间件中 特别是 CSRF 检查 检查现有会话值 即身份验证或预览页面 等 我读了关于此的几篇文章 http justinas org writing http middle
  • 我应该避免在 golang 中使用单例包吗?

    现在我有一个包裹store包含以下内容 package store var db Database func Open url string error open db connection func FindAll model inter
  • 递归追加到切片不起作用

    我正在尝试学习 Go 但我不明白为什么递归调用堆栈末尾的这段代码返回一个空切片 有帮助吗 还tmp甚至似乎没有在调试器中注册 func main input 3 int 4 6 7 expected 6 7 4 6 7 4 6 4 7 fm
  • 是否可以使用 go:generate 重定向 stdin/stdout

    我有一个充当管道的工具 它从标准输入读取数据并将源代码写入标准输出 是否可以设置输入 输出重定向并将此类工具与 go generate 一起使用 就像是 go generate tool lt file txt gt file go 我想出
  • bazel go_embed_data“无法嵌入”

    我将以下 bazel BUILD 配置为 gazelle name gazelle go embed data name static files srcs glob static package main var staticFS go
  • 为什么 Go 中的函数不能命名为“init”?

    所以 今天在编码时我发现创建一个名为init产生错误method init not found 但是当我将其重命名为startup一切都很好 init 这个词是为 Go 中的某些内部操作而保留的 还是我在这里遗漏了一些东西 是的 该功能in
  • 与 Reflect.StructTag.Get 不兼容

    我当时在 Google Cloud 中工作 一切都很好 但是当我在 PC 中克隆所有项目时 每个 JSON 结构中都有此消息 结构体字段标签bson edad json edad omitempty 与reflect StructTag G
  • Golang 有 libfaketime 替代品吗?

    我想自动化一些测试 我必须操纵系统时间来检查用 golang 编写的程序的身份验证行为 根据这个帖子 https stackoverflow com questions 36024872 libfaketime doesnt work wi
  • 交叉编译共享库

    我想知道是否有可能 如果是的话 如何 与 Go 交叉编译共享库 假设我有这段代码 package main import C export DoubleIt func DoubleIt x int int return x 2 func m
  • Golang SSL TCP套接字证书配置

    我正在创建一个 Go TCP 服务器 不是 http s 并且尝试将其配置为使用 SSL 我有一个 StartCom 免费 SSL 证书 我正在尝试使用它来完成此任务 我的服务器代码如下所示 cert err tls LoadX509Key
  • 如何避免 Google App Engine 标准环境中 Gorilla 会话的内存泄漏?

    我正在使用 Gorilla 在 Google App Engine 上启用会话变量 到目前为止 我只导入了 github com gorilla sessions 但 Gorilla 的页面显示 如果您不使用 gorilla mux 则需要
  • 如何退出执行延迟调用的 go 程序?

    我需要使用defer释放手动创建的分配C图书馆 但我还需要os Exit在某个时刻具有非 0 状态 棘手的部分是os Exit跳过任何延迟指令 package main import fmt import os func main defe
  • gRPC 服务器如何注意到客户端已取消服务器端流式调用?

    我想使用 gRPC 让客户端订阅服务器生成的事件 我有一个 RPC 声明如下 rpc Subscribe SubscribeRequest returns stream SubscribeResponse 其中返回的流是无限的 要 取消订阅
  • 使用指针接收器调用函数的 Go 语法

    在Go中 如果我定义一个带有指针的函数作为接收者 它是否应该只允许从指针调用该函数 为什么从值本身调用这个函数就可以 并且有同样的效果 例如 在以下程序中 m1 reset 和 m2 reset 具有相同的效果 即使 m1 是一个值而 m2
  • Golang 使用 gomail.v2 实现多个收件人

    我通过 gomail v2 发送电子邮件的唯一方法是在 for 循环中对每封电子邮件使用 Send 函数 但我需要向其他电子邮件地址显示已发送相同的电子邮件 for recipient range os Args 3 mail SetAdd
  • Golang 处理数据库连接的“最佳实践”

    我有一个用 Go 编写的 Web 服务 目前我有一个全局包 我可以在任何地方导入它 其中包含与 MongoDB 的连接 通过 MGO 但我不得不说 这对我来说感觉非常恶心 在 Go 中维护与数据源的连接的最佳实践是什么 我来自 PHP 世界

随机推荐

  • 更改金额后 PayPal React 显示额外按钮

    没有react paypal button v2 有60 KB的开销 类似问题here但他们建议反应贝宝按钮 v2 我正在尝试制作一个 React PayPal 按钮来更改道具更改的计费金额 我用道具价格调用以下组件 每次价格变化时我想重新
  • python递归返回None类型[重复]

    这个问题在这里已经有答案了 没看懂 怎么退货List代替None class foo def recursion aList if isGoal aList 1 return aList for item in anotherList ne
  • SQLPlus 尝试删除包两次

    在 SQLPlus 中执行脚本时我遇到了一个问题 script sql 包含以下行 some pkg pks some pkg pkb drop package some pkg 打电话后 gt sqlplus 用户 密码 dbname s
  • 在 Windows 上构建支持 SSL 的 libcurl

    我在 Win32 C 应用程序中使用 libcurl 我已将curlib vcproj 项目添加到我的解决方案中 并将其他项目设置为依赖于它 如何在启用 SSL 支持的情况下构建它 这个答案已经过时了 请参阅此处的实际指南https cur
  • cudaMemset 在 __device__ 变量上失败

    我使用时遇到问题cudaMemset在设备变量上 是否可以使用对设备变量的引用cudaMemset 或者只是缺少编译器标志或库的问题 我正在使用 cuda 4 1 并且 NVRM 版本 NVIDIA UNIX x86 64 内核模块 285
  • 如何向 Android AsyncTask 传递值

    这是我第一次使用 AsyncTask 对于传递值可能也有点困惑 我有 4 个ArrayList
  • C++中如何连接字符串?

    string degreesToDMS double angle int intpart 0 int intpart2 0 int intpart3 0 return floor angle lt lt xb0 lt lt modf ang
  • 一个 Java 文件,但两个类

    我的项目中有一些课程 编译后 我找到两个 java 文件到每个类 name class 和 name class 原因可能是什么 我认为这些课程没有什么特别的 问候 它是一个匿名内部类 例如 new Runnable Edit 评论中的一些
  • Spring - 没有可用于当前线程的实际事务的 EntityManager - 无法可靠地处理“持久”调用

    当尝试调用 persist 方法将实体模型保存到 Spring MVC Web 应用程序中的数据库时 出现此错误 在互联网上确实找不到与此特定错误相关的任何帖子或页面 EntityManagerFactory bean 似乎有问题 但我对
  • 安装 Xcode 4 并保留 Xcode 3?

    我已经读过很多次我们可以安装 Xcode 4 并保留 Xcode 3 但是 我还了解到 Xcode 4 GM 不可能做到这一点 有人成功做到过吗 Update 好的 我已经安装了 不同的文件夹 但一开始总是崩溃 xcode遇到内部逻辑错误
  • Android P 无法写入文件

    我无法在 Android P 存储卡中写入文件 相同的代码在 Android O 中运行良好 new File file getParent mkdirs output new ObjectOutputStream new FileOutp
  • C#:System.Net.WebException:底层连接已关闭

    我有以下代码 String url a valid url String requestXml File ReadAllText filePath opens file reads all text and closes it byte b
  • 如何在没有 Mac 的情况下构建 iPhone Xamarin 应用程序?

    我正在开发 xamarin 表单应用程序 我可以生成 APK 并在我的 Android 设备上运行它 但如果没有 Mac 我怎样才能对 iPhone 做同样的事情呢 有没有办法在应用程序中心或 azure devops 上构建我的应用程序并
  • Android 应用程序构建在 geotools 库上,缺少本机 java 库

    我想使用 eclipse 在 Android 应用程序中使用 geotools 目前是 8 0 M3 也可能是 2 7 3 库 win7 教授 4GB 内存 但是构建过程崩溃了 我收到以下错误 未处理的事件循环异常 Java 堆空间 jav
  • XAMPP 服务器不加载 CSS 文件 [重复]

    这个问题在这里已经有答案了 实际上我正在使用 XAMPP 服务器开发一个小项目 大多数时候我都会遇到这个疯狂的问题 当我更改 CSS 文件中的任何内容时 它没有任何效果 但是当我重新启动我的 XAMPP apache 服务器几次时 它工作正
  • 关于C语法的几个问题

    我有几个关于 C 语法的问题 ch char malloc sizeof char strlen src 第一个括号 char 是什么意思 c getch switch c case 1 我的老师问为什么使用 这种类型 引号而不是 双引号
  • `const int a = 1;` 是 `a` 常量表达式,如果 `a` 具有自动存储期限

    N4527 5 20 表达式常量 p2 条件表达式 e 是 a核心常量表达式除非 e 的评估遵循以下规则 抽象机 1 9 将评估以下表达式之一 2 7 左值到右值的转换 4 1 除非它应用于 2 7 1 引用完整非易失性 const 的整型
  • 为什么我无法将 Git Url 添加到我的 Jenkins 中?

    我对 git 和 Jenkins 都很陌生 我添加了ssh当我执行以下操作时 将密钥指向 bitbucket 和我的本地计算机 git clone email protected username repo git 我可以克隆 但是当我添加
  • Inno Setup Compiler:如何使用给定的 url 自动启动默认浏览器?

    我正在尝试使用给定的网址启动我的默认浏览器 chrome http localhost folder 通过使用inno setup compiler for windows 安装程序完成后 我运行 wamp 管理器 我必须在其中写什么run
  • Go 程序的主 Goroutine 和衍生 Goroutine 之间的区别

    创建服务器时使用gRPC 如果我开始gRPC服务器在主进程中 它可以处理来自客户端的请求 数千个 但是 如果我将服务器作为 goroutine 启动 它只能处理一些请求 数百个 然后就会卡住 我已经用一个非常简单的示例 google gol