逃逸分析显示通道作为泄漏参数

9
我想要做的事情: 尝试理解/构建一个具有三个阶段的go管道。第一阶段写入通道A, 第二阶段有多个go例程。每个go例程从通道A读取数据,执行某些操作并将结果写入到Bn通道(B1、B2……Bn)。第三阶段创建n(=第二阶段中通道的总数)个go例程,每个go例程从第二阶段的一个通道中读取数据。这是基于https://blog.golang.org/pipelines所描述的有限并行性。
问题: 管道按预期正常工作,操作被分配给多个go例程。但是当我进行逃逸分析时发现,从一个阶段发送到另一个阶段的通道参数被报告为“泄漏的参数”。
代码片段: 为简单起见,我发布了显示第一阶段通道创建和打印从第一阶段通道读取值的第二阶段的代码。
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标志的参数?

是的。问题是什么? - Volker
1
@Volker,逃逸分析中的泄漏参数是否意味着资源泄漏?Go协程按预期退出,并且通道在此处不会永远阻塞。那么为什么它被显示为泄漏?我有什么遗漏吗? - object
泄漏逃逸分析中的参数意味着资源泄漏吗?当然不是。你为什么会这样想? - Volker
4
“你为什么这样想?” 可以合理地假设,“泄漏(leaking)”是不好的,与词根“泄(leak)”有关。我很难想出一个泄漏是好事的例子,比如漏水的桶,漏气的油箱,“排尿(taking a leak)”,漏电的电容器,漏洞百出的船只,漏洞百出的抽象概念等。对于高性能 Go 专家来说可能很显而易见,但对于其他人来说,提供文档链接和简要说明“泄漏参数(leaking param)”指的是什么,会很有帮助。 - Davos
1个回答

14
涉及的参数是引用类型的通道。它们被捕获在createStageTwo()中创建的闭包中,并且可以在createStageTwo()返回后继续在该闭包的go例程中使用。因此,它们被标记为泄漏参数。如果不是这样,它们将被放置在堆栈上,并在main()完成时失效。
这并不意味着您有问题。逃逸分析并不是用来检测资源泄漏的,大多数人永远不需要使用它。(它对于性能问题可能很有用,其中某些东西被放置在GC堆上,而您不希望如此。)
(抱歉@Volker,我最初在评论中发布了我的答案,这让您的问题悬而未决。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接