gpt4 book ai didi

go - Go 程序的主 goroutine 和派生 goroutine 之间的区别

转载 作者:IT王子 更新时间:2023-10-29 00:45:02 25 4
gpt4 key购买 nike

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

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

示例 link .示例修改部分如下。

greeter_server/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 {
}
}

greeter_client/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 的栈是无限的:

One of the key features of Goroutines is their cost; they are cheap to create in terms of initial memory footprint (as opposed to the 1 to 8 megabytes with a traditional POSIX thread) and their stack grows and shrinks as necessary. This allows a Goroutine to start with a single 4096 byte stack which grows and shrinks as needed without the risk of ever running out.

There is however one detail I have withheld until now, which links the accidental use of a recursive function to a serious case of memory exhaustion for your operating system, and that is, when new stack pages are needed, they are allocated from the heap.

As your infinite function continues to call itself, new stack pages are allocated from the heap, permitting the function to continue to call itself over and over again. Fairly quickly the size of the heap will exceed the amount of free physical memory in your machine, at which point swapping will soon make your machine unusable.

The size of the heap available to Go programs depends on a lot of things, including the architecture of your CPU and your operating system, but it generally represents an amount of memory that exceeds the physical memory of your machine, so your machine is likely to swap heavily before your program ever exhausts its heap.

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


空循环:

for{
}

使用 100% 的 CPU 核心,根据您可能使用的用例等待某些操作:
- sync.WaitGroup 喜欢 this
- 选择{} this
- channel
- time.Sleep


Is it because spawned goroutines stack size is very small (2Kbytes), and the main goroutine's much larger?

没有,你可以试试这两个例子,看看goroutines的stack limit是一样的:
The Go Playground 上的一个主要 goroutine ,
The Go Playground 上尝试第二个 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

在具有 8 GB RAM 的 PC 上输出:

runtime: goroutine stack exceeds 1_000_000_000-byte limit
fatal error: stack overflow

关于go - Go 程序的主 goroutine 和派生 goroutine 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39493692/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com