GC efficiency: Is sending pointers through channels via intermediat interfaces bad?

blov · · 445 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<pre><code>package main import ( &#34;fmt&#34; ) type Anything struct { Foo string Bar string } type Res struct{ Data interface{} Error error } type ResChan chan Res func fn1() ResChan { r := make(ResChan, 1) go func(){ res := Res{} a := Anything{ Foo: &#34;foobar&#34;, Bar: &#34;barfoo&#34;, } res.Data = a r &lt;- res close(r) return }() return r } func fn2() ResChan { r := make(ResChan, 1) go func(){ res := Res{} a := &amp;Anything{ Foo: &#34;foobar&#34;, Bar: &#34;barfoo&#34;, } res.Data = a r &lt;- res close(r) return }() return r } func main() { resFn1 := &lt;- fn1() aFn1 := resFn1.Data.(Anything) fmt.Printf(&#34;%v\n&#34;, aFn1) resFn2 := &lt;- fn2() aFn2 := resFn2.Data.(*Anything) fmt.Printf(&#34;%v\n&#34;, aFn2) } </code></pre> <p><a href="https://play.golang.org/p/TNWMjKLbCh" rel="nofollow">https://play.golang.org/p/TNWMjKLbCh</a> </p> <p>Can the gc free <code>fn2</code> allocated memory?<br/> Where does <code>a</code> life in the memory?<br/> I&#39;m guessing because in <code>fn2</code> the pointer gets assigned to res.Data it lifes inside the goroutines scope so the goroutine can&#39;t be freed by the gc?<br/> Is this even an issue I have to worry about?<br/> What would be your prefered way of doing this?<br/> Can someone enlighten me what&#39;s actually happening in the memory here? </p> <hr/>**评论:**<br/><br/>Sythe2o0: <pre><blockquote> <p>Is this even an issue I have to worry about?</p> </blockquote> <p>If you are worried about accessing freed memory, no, that won&#39;t happen. For efficiency, instead of planning around elements of the compiler (that could change in later releases) I would benchmark it.</p></pre>ChristophBerger: <pre><p>The Go compiler does an escape analysis of all the objects that get created. If it finds that an object created inside a local scope is used outside this scope, this object automatically gets created on the heap rather than on the stack. (Hence it „escapes“ the local scope.)</p> <p>When I run your code with escape analyis enabled and inlining disabled, I get this output:</p> <pre><code>$ go run -gcflags &#39;-m -l&#39; main.go # command-line-arguments ./main.go:22:5: func literal escapes to heap ./main.go:22:5: func literal escapes to heap ./main.go:20:11: make(ResChan, 1) escapes to heap ./main.go:30:12: a escapes to heap ./main.go:43:5: func literal escapes to heap ./main.go:43:5: func literal escapes to heap ./main.go:41:11: make(ResChan, 1) escapes to heap ./main.go:51:12: a escapes to heap ./main.go:48:9: &amp;Anything literal escapes to heap ./main.go:64:13: aFn1 escapes to heap ./main.go:68:13: aFn2 escapes to heap ./main.go:64:12: main ... argument does not escape ./main.go:68:12: main ... argument does not escape {foobar barfoo} &amp;{foobar barfoo} </code></pre> <p>Anything that escapes to heap is not bound to a local scope anymore, and the GC can deal with it like with any object on the heap. For <code>a</code>, this is definitely the case.</p></pre>cirowrc: <pre><p>oh, I didn&#39;t know about those flags! Thanks a bunch!</p></pre>nsd433: <pre><p>Some of the wording you&#39;re using is unclear. So I&#39;ll make some assumptions in order to answer.</p> <p>Inside fn2() two allocates happen, one of a channel, and one of a closure which holds the channel. The closure is passed to the child goroutine. The closure can be gc&#39;ed once both fn2 and the child goroutine of fn2 return, and the channel can be gc&#39;ed once the closure is gc-able and main completes the &#39;&lt;- fn2()&#39; operation.</p> <p>&#39;a&#39; is a local variable of the goroutine of fn2. &#39;a&#39; is a pointer to a struct which itself was allocated on the heap (the struct escapes via the channel). &#39;a&#39; lives on the stack (and probably just in a register since it only needs to live for 2 statements). The res.Data interface{} contains a copy of &#39;a&#39; in its value field.</p> <p>I&#39;m not sure what you mean by a goroutine being freed by gc. But in general goroutines are linked to by the scheduler, which is a global object, and thus a goroutine will not be gc&#39;ed until it terminates. I&#39;m not sure if that&#39;s what you&#39;re asking.</p> <p>I don&#39;t know what worries you, but there&#39;s nothing obviously wrong with the code you have here. It&#39;s not going to crash or do strange things.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

445 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传