gpt4 book ai didi

go - 逃逸分析显示 channel 为泄漏参数

转载 作者:IT王子 更新时间:2023-10-29 00:43:13 24 4
gpt4 key购买 nike

我想做什么:我正在尝试理解/构建一个包含三个阶段的 go 管道。 Stage 1 写入 channel A。 Stage 2 有多个 go 例程。每个 go 例程从 channel A 读取,执行一些操作并将结果写入 channel Bn( channel B1,B2..Bn)。第 3 阶段创建了 n(=第 2 阶段的 channel 总数)个 go 例程,每个 go 例程从第 2 阶段的一个 channel 读取。它基于 https://blog.golang.org/pipelines 中描述的有限并行性。

问题:管道按预期工作正常,操作分布在 go 例程中。但是当我进行逃逸分析时,发现从一个阶段发送到另一个阶段的 channel 参数被报告为“泄漏参数”。

代码片段:为简单起见,我发布了显示阶段 1 channel 创建的代码,以及打印从阶段 channel 1 读取的值的阶段 2。

package main

import "fmt"

func createStageOne(numOfJobs int) <-chan int {
stageOneChannel := make(chan int)
go func(nJobs int) {
for i := 0; i < nJobs; i++ {
stageOneChannel <- i
}
close(stageOneChannel)
}(numOfJobs)
return stageOneChannel
} // stageOneChannel closes and go routine exits once nJobs are completed

func createStageTwo(in <-chan int, completionFlag chan struct{}) {
go func() {
for n := range in {
fmt.Println("Received from stage 1 channel ", n)
}
completionFlag <- struct{}{}
}()
}// Comes out of for loop when stage 1 channel closes and go routine also exits


func main() {
numOfJobs := 10
stageOneChannel := createStageOne(numOfJobs)

done := make(chan struct{})
createStageTwo(stageOneChannel, done)

<-done
}

这里是逃逸分析结果

$ go build -gcflags "-m -l"
# concurrentHTTP/stackoverflow
./pipeline.go:7:5: func literal escapes to heap
./pipeline.go:7:5: func literal escapes to heap
./pipeline.go:6:25: make(chan int) escapes to heap
./pipeline.go:17:5: func literal escapes to heap
./pipeline.go:17:5: func literal escapes to heap
./pipeline.go:16:21: leaking param: in
./pipeline.go:16:36: leaking param: completionFlag
./pipeline.go:19:16: "Received from stage 1 channel " escapes to heap
./pipeline.go:19:16: n escapes to heap
./pipeline.go:19:15: createStageTwo.func1 ... argument does not escape
./pipeline.go:29:14: make(chan struct {}) escapes to heap

为什么逃逸分析报告在 incompletionFlag 标志上泄漏参数?

最佳答案

有问题的参数是引用类型的 channel 。它们在 createStageTwo() 中创建的闭包中被捕获,并且可以在 createStageTwo() 返回时继续在该闭包的 go 例程中使用。因此,它们被标记为泄漏参数。如果不是,则它们将被放入堆栈并在 main() 完成处理它们时变为无效。

这并不意味着您有问题。逃逸分析用于检测资源泄漏,大多数人永远不需要使用它。 (它对于在 GC 堆上放置您不期望的东西时的性能问题很有用。)

(抱歉@Volker,我最初在评论中发布了我的答案,导致您的问题悬而未决。)

关于go - 逃逸分析显示 channel 为泄漏参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54623302/

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