What is escape analysis and what do I need to know about it?

xuanbao · · 710 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;ve seen a lot of talk lately about how go does escape analysis. Specifically about recent changes in the GC.</p> <p>Can someone elaborate on what is happening behind the scenes and what are some red flags I should look out for?</p> <p>*I realized after Caleb answered my original question, I was really asking about this instead.</p> <hr/>**评论:**<br/><br/>calebdoxsey: <pre><p>It can get pretty technical, but the basic idea is that memory is allocated in two places: on the stack or on the heap.</p> <p>Every goroutine has a stack associated with it which contains local variables and function calls. For example if we had this:</p> <pre><code>func f1() int { a := 1 return a } func f2() int { b := 2 return b + f1() } func main() { fmt.Println(f2()) } </code></pre> <p>As we executed the code it would do something like this:</p> <pre><code>1. |f2 ret | call f2 and leave space for its return value 2. |b = 2 | allocate on the stack a local variable for b |f2 ret | 3. |f1 ret | call f1 and leave space for its return value |b = 2 | |f2 ret | 4. |a = 1 | allocate on the stack a local variable for a |f1 ret | |b = 2 | |f2 ret | 5. |f1 ret = 1| f1 finishes and a is removed from the stack |b = 2 | |f2 ret | 6. |f2 ret = 3| f2 finishes and f1&#39;s return and b are removed </code></pre> <p>If that makes sense.</p> <p>When memory is allocated on the heap it&#39;s just a pile of objects that could&#39;ve come from anywhere and your stack will contain pointers to them. (The heap can also contain pointers)</p> <p>Now the benefit to stack allocation is that when a function finishes it cleans up everything, but for heap allocation you have to free that memory when objects are no longer needed.</p> <p>So to get back to the original question: escape analysis refers to the ability of the compiler to determine whether or not to use stack allocation or heap allocation. If a pointer never leaves a function (you don&#39;t return a pointer, send it over a channel, etc...), then there&#39;s no need to allocate the object on the heap (unless its really big or something). And the less things you put on the heap, the less work the garbage collector has to do, the less fragmented memory gets, etc...</p> <p>In other words the compiler is &#34;analyzing&#34; code to determine whether or not pointers ever &#34;escape&#34; a function.</p> <p>Maybe someone else can chime in on the technical details of how Go chooses to do this.</p></pre>anoland: <pre><blockquote> <p>In other words the compiler is &#34;analyzing&#34; code to determine whether or not pointers ever &#34;escape&#34; a function.</p> </blockquote> <p>Good answer. That helps. Thanks.</p></pre>mparker762: <pre><p>It&#39;s checking to see if <em>any</em> binding escapes its declaring function, not just pointers. If so, then they are candidates for being hoisted out into the heap. Whether or not this happens depends on other factors. Immutable bindings can stay on the stack and closure gets a copy. Or if the compiler can prove that the binding is only used by calls further down the call stack (a so-called &#39;downward funarg&#39;) then the binding could potentially remain stack allocated. But if the escaping binding escapes up the call stack (a so-called &#39;upward funarg&#39;) or outward, e.g. it is captured by a closure that is returned from the declaring function, or stored in a global, or used to start a goroutine etc, then the binding will have to be heap allocated so the it can survive the pop of the stack frame for the function where it was created.</p></pre>dsymonds: <pre><p>In addition to <a href="/u/calebdoxsey">/u/calebdoxsey</a>&#39;s good answer, the direct answer to the question in the title is: You don&#39;t need to know anything about it. It&#39;s a compiler optimisation.</p></pre>binaryblade: <pre><p>I think it would be ideal if that were really the case, but a knowledge that anytime you take a pointer to something there is a high probability of a heap allocation is good to keep in mind. In C or C++ you can take the pointer of a stack variable and know it will always exist on the stack with the price that if you access it after return your program will most likely explode. While in go the agreement is, you shouldn&#39;t be able to blow up your program and the compiler will sacrifice performance to ensure that.</p></pre>comrade_donkey: <pre><p>It&#39;s a performance optimization whereby values that don&#39;t outlive a defined scope can be put on the (already allocated) execution stack instead of allocating memory from the heap for them, which can be really expensive, especially if done repeatedly.</p> <p>Anything that lives on the heap is collected by the garbage collector, whereby values that live on the stack get &#34;popped&#34; off when they&#39;re not needed anymore by the program flow. So values on the stack are cheaper in that aspect as well.</p> <p>Normally, if you use <code>new(...)</code>, you get a pointer to a newly heap-allocated object. However, if the compiler can determine that the pointer never escapes the scope in which it was instantiated, then the pointed-to object may be placed on the stack, relieving the garbage collector of having to collect it later.</p></pre>

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

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