Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Currently, go uses a <a href="http://en.wikipedia.org/wiki/Mark-and-sweep#Na.C3.AFve_mark-and-sweep" rel="nofollow noreferrer">mark-and-sweep garbage collector</a>, which in general does not define when the object is thrown away.</p> <p>However, if you look closely, there is a go routine called <a href="https://github.com/golang/go/blob/be589f8d2b721aa86fd5e406733f61a5ed245d3a/src/runtime/proc.go#L4185" rel="nofollow noreferrer"><code>sysmon</code></a> which essentially runs as long as your program does and calls the GC periodically:</p> <pre><code>// forcegcperiod is the maximum time in nanoseconds between garbage // collections. If we go this long without a garbage collection, one // is forced to run. // // This is a variable for testing purposes. It normally doesn't change. var forcegcperiod int64 = 2 * 60 * 1e9 (...) // If a heap span goes unused for 5 minutes after a garbage collection, // we hand it back to the operating system. scavengelimit := int64(5 * 60 * 1e9) </code></pre> <p><a href="https://github.com/golang/go/blob/be589f8d2b721aa86fd5e406733f61a5ed245d3a/src/runtime/proc.go#L4175-L4180" rel="nofollow noreferrer"><code>forcegcperiod</code></a> determines the period after which the GC is called by force. <a href="https://github.com/golang/go/blob/be589f8d2b721aa86fd5e406733f61a5ed245d3a/src/runtime/proc.go#L4191-L4193" rel="nofollow noreferrer"><code>scavengelimit</code></a> determines when spans are returned to the operating system. <a href="https://github.com/golang/go/blob/be589f8d2b721aa86fd5e406733f61a5ed245d3a/src/runtime/malloc.go#L22" rel="nofollow noreferrer">Spans are a number of memory pages</a> which can hold several objects. They're kept for <code>scavengelimit</code> time and are freed if no object is on them and <code>scavengelimit</code> is exceeded.</p> <p>Further down in the code you can see that there is a trace option. You can use this to see, whenever the scavenger thinks he needs to clean up:</p> <pre><code>$ GOGCTRACE=1 go run gc.go gc1(1): 0+0+0 ms 0 -&gt; 0 MB 423 -&gt; 350 (424-74) objects 0 handoff gc2(1): 0+0+0 ms 1 -&gt; 0 MB 2664 -&gt; 1437 (2880-1443) objects 0 handoff gc3(1): 0+0+0 ms 1 -&gt; 0 MB 4117 -&gt; 2213 (5712-3499) objects 0 handoff gc4(1): 0+0+0 ms 2 -&gt; 1 MB 3128 -&gt; 2257 (6761-4504) objects 0 handoff gc5(1): 0+0+0 ms 2 -&gt; 0 MB 8892 -&gt; 2531 (13734-11203) objects 0 handoff gc6(1): 0+0+0 ms 1 -&gt; 1 MB 8715 -&gt; 2689 (20173-17484) objects 0 handoff gc7(1): 0+0+0 ms 2 -&gt; 1 MB 5231 -&gt; 2406 (22878-20472) objects 0 handoff gc1(1): 0+0+0 ms 0 -&gt; 0 MB 172 -&gt; 137 (173-36) objects 0 handoff getting memory gc2(1): 0+0+0 ms 381 -&gt; 381 MB 203 -&gt; 202 (248-46) objects 0 handoff returning memory getting memory returning memory </code></pre> <p>As you can see, no gc invoke is done between getting and returning. However, if you change the delay from 5 seconds to 3 minutes (more than the 2 minutes from <code>forcegcperiod</code>), the objects are removed by the gc:</p> <pre><code>returning memory scvg0: inuse: 1, idle: 1, sys: 3, released: 0, consumed: 3 (MB) scvg0: inuse: 381, idle: 0, sys: 382, released: 0, consumed: 382 (MB) scvg1: inuse: 1, idle: 1, sys: 3, released: 0, consumed: 3 (MB) scvg1: inuse: 381, idle: 0, sys: 382, released: 0, consumed: 382 (MB) gc9(1): 1+0+0 ms 1 -&gt; 1 MB 4485 -&gt; 2562 (26531-23969) objects 0 handoff gc10(1): 1+0+0 ms 1 -&gt; 1 MB 2563 -&gt; 2561 (26532-23971) objects 0 handoff scvg2: GC forced // forcegc (2 minutes) exceeded scvg2: inuse: 1, idle: 1, sys: 3, released: 0, consumed: 3 (MB) gc3(1): 0+0+0 ms 381 -&gt; 381 MB 206 -&gt; 206 (252-46) objects 0 handoff scvg2: GC forced scvg2: inuse: 381, idle: 0, sys: 382, released: 0, consumed: 382 (MB) getting memory </code></pre> <p>The memory is still not freed, but the GC marked the memory region as unused. Freeing will begin when the used span is unused and older than <code>limit</code>. From scavenger code:</p> <pre><code>if(s-&gt;unusedsince != 0 &amp;&amp; (now - s-&gt;unusedsince) &gt; limit) { // ... runtime·SysUnused((void*)(s-&gt;start &lt;&lt; PageShift), s-&gt;npages &lt;&lt; PageShift); } </code></pre> <p>This behavior may of course change over time, but I hope you now get a bit of a feel when objects are thrown away by force and when not. </p> <p>As pointed out by zupa, releasing objects may not return the memory to the operating system, so on certain systems you may not see a change in memory usage. This seems to be the case for Plan 9 and Windows according to <a href="https://groups.google.com/forum/#!topic/golang-nuts/vfmd6zaRQVs" rel="nofollow noreferrer">this thread on golang-nuts</a>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload