Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It has already been explained that calling <code>system.gc()</code> <em>may</em> do nothing, and that any code that "needs" the garbage collector to run is broken.</p> <p>However, the pragmatic reason that it is bad practice to call <code>System.gc()</code> is that it is inefficient. And in the worst case, it is <strong>horribly inefficient</strong>! Let me explain.</p> <p>A typical GC algorithm identifies garbage by traversing all non-garbage objects in the heap, and inferring that any object not visited must be garbage. From this, we can model the total work of a garbage collection consists of one part that is proportional to the amount of live data, and another part that is proportional to the amount of garbage; i.e. <code>work = (live * W1 + garbage * W2)</code>. </p> <p>Now suppose that you do the following in a single-threaded application.</p> <pre><code>System.gc(); System.gc(); </code></pre> <p>The first call will (we predict) do <code>(live * W1 + garbage * W2)</code> work, and get rid of the outstanding garbage.</p> <p>The second call will do <code>(live* W1 + 0 * W2)</code> work and reclaim nothing. In other words we have done <code>(live * W1)</code> work and <em>achieved absolutely nothing</em>.</p> <p>We can model the efficiency of the collector as the amount of work needed to collect a unit of garbage; i.e. <code>efficiency = (live * W1 + garbage * W2) / garbage</code>. So to make the GC as efficient as possible, we need to <em>maximize</em> the value of <code>garbage</code> when we run the GC; i.e. wait until the heap is full. (And also, make the heap as big as possible. But that is a separate topic.)</p> <p>If the application does not interfere (by calling <code>System.gc()</code>), the GC will wait until the heap is full before running, resulting in efficient collection of garbage<sup>1</sup>. But if the application forces the GC to run, the chances are that the heap won't be full, and the result will be that garbage is collected inefficiently. And the more often the application forces GC, the more inefficient the GC becomes.</p> <p>Note: the above explanation glosses over the fact that a typical modern GC partitions the heap into "spaces", the GC may dynamically expand the heap, the application's working set of non-garbage objects may vary and so on. Even so, the same basic principal applies across the board to all true garbage collectors<sup>2</sup>. It is inefficient to force the GC to run.</p> <hr> <p><sup>1 - This is how the "throughput" collector works. Concurrent collectors such as CMS and G1 use different criteria to decide when to start the garbage collector.</sup></p> <p><sup>2 - I'm also excluding memory managers that use reference counting exclusively, but no current Java implementation uses that approach ... for good reason.</sup></p>
    singulars
    1. This table or related slice is empty.
    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. 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