Sophie

Sophie

distrib > Mageia > 4 > x86_64 > by-pkgid > f800694edefe91adea2624f711a41a2d > files > 1904

php-manual-en-5.5.7-1.mga4.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>Collecting Cycles</title>

 </head>
 <body><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="features.gc.refcounting-basics.html">Reference Counting Basics</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="features.gc.performance-considerations.html">Performance Considerations</a></div>
 <div class="up"><a href="features.gc.html">Garbage Collection</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div><hr /><div id="features.gc.collecting-cycles" class="sect1">
   <h2 class="title">Collecting Cycles</h2>
   <p class="para">
    Traditionally, reference counting memory mechanisms, such as that used
    previously by PHP, fail to address circular reference memory leaks.
    As of 5.3.0 PHP however implements the synchronous algorithm from the 
    <a href="http://www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf" class="link external">&raquo;&nbsp;Concurrent Cycle Collection in Reference Counted Systems</a>
    paper which addresses that issue.
   </p>
   <p class="para">
    A full explanation of how the algorithm works would be slightly beyond the
    scope of this section, but the basics are explained here. First of all,
    we have to establish a few ground rules. If a refcount is increased, it&#039;s
    still in use and therefore, not garbage. If the refcount is decreased and
    hits zero, the zval can be freed. This means that garbage cycles can only
    be created when a refcount argument is decreased to a non-zero value.
    Secondly, in a garbage cycle, it is possible to discover which parts are
    garbage by checking whether it is possible to decrease their refcount by
    one, and then checking which of the zvals have a refcount of zero. 
   </p>
   <p class="para">
     <div class="mediaobject">
      
      <div class="imageobject">
       <img src="images/12f37b1c6963c1c5c18f30495416a197-gc-algorithm.png" alt="Garbage collection algorithm" width="614" height="814" />
      </div>
     </div>
   </p>
   <p class="para">
    To avoid having to call the checking of garbage cycles with every possible
    decrease of a refcount, the algorithm instead puts all possible roots
    (zvals) in the &quot;root buffer&quot; (marking them &quot;purple&quot;). It also makes sure
    that each possible garbage root ends up in the buffer only once. Only when
    the root buffer is full does the collection mechanism start for all the
    different zvals inside. See step A in the figure above.
   </p>
   <p class="para">
    In step B, the algorithm runs a depth-first search on all possible roots
    to decrease by one the refcounts of each zval it finds, making sure not to
    decrease a refcount on the same zval twice (by marking them as &quot;grey&quot;). In
    step C, the algorithm again runs a depth-first search from each root node,
    to check the refcount of each zval again. If it finds that the refcount is
    zero, the zval is marked &quot;white&quot; (blue in the figure). If it&#039;s larger than
    zero, it reverts the decreasing of the refcount by one with a depth-first
    search from that point on, and they are marked &quot;black&quot; again. In the last
    step (D), the algorithm walks over the root buffer removing the zval roots
    from there, and meanwhile, checks which zvals have been marked &quot;white&quot; in
    the previous step. Every zval marked as &quot;white&quot; will be freed.
   </p>
   <p class="para">
    Now that you have a basic understanding of how the algorithm works, we
    will look back at how this integrates with PHP. By default, PHP&#039;s garbage
    collector is turned on. There is, however, a <var class="filename">php.ini</var>
    setting that allows you to change this:
    <a href="info.configuration.html#ini.zend.enable-gc" class="link">zend.enable_gc</a>.
   </p>
   <p class="para">
    When the garbage collector is turned on, the cycle-finding algorithm as
    described above is executed whenever the root buffer runs full. The root
    buffer has a fixed size of 10,000 possible roots (although you can alter
    this by changing the <em>GC_ROOT_BUFFER_MAX_ENTRIES</em> constant in
    <em>Zend/zend_gc.c</em> in the PHP source code, and re-compiling
    PHP). When the garbage collector is turned off, the cycle-finding
    algorithm will never run. However, possible roots will always be recorded
    in the root buffer, no matter whether the garbage collection mechanism has
    been activated with this configuration setting.
   </p>
   <p class="para">
    If the root buffer becomes full with possible roots while the garbage
    collection mechanism is turned off, further possible roots will simply not
    be recorded. Those possible roots that are not recorded will never be
    analyzed by the algorithm. If they were part of a circular reference
    cycle, they would never be cleaned up and would create a memory leak. 
   </p>
   <p class="para">
    The reason why possible roots are recorded even if the mechanism has been
    disabled is because it&#039;s faster to record possible roots than to have to
    check whether the mechanism is turned on every time a possible root could
    be found. The garbage collection and analysis mechanism itself, however,
    can take a considerable amount of time.
   </p>
   <p class="para">
    Besides changing the <a href="info.configuration.html#ini.zend.enable-gc" class="link">zend.enable_gc</a> configuration
    setting, it is also possible to turn the garbage collecting mechanism on
    and off by calling  <span class="function"><a href="function.gc-enable.html" class="function">gc_enable()</a></span> or
     <span class="function"><a href="function.gc-disable.html" class="function">gc_disable()</a></span> respectively.  Calling those functions has
    the same effect as turning on or off the mechanism with the configuration
    setting. It is also possible to force the collection of cycles even if the
    possible root buffer is not full yet. For this, you can use the
     <span class="function"><a href="function.gc-collect-cycles.html" class="function">gc_collect_cycles()</a></span> function. This function will return
    how many cycles were collected by the algorithm. 
   </p>
   <p class="para">
    The rationale behind the ability to turn the mechanism on and off, and to
    initiate cycle collection yourself, is that some parts of your application
    could be highly time-sensitive. In those cases, you might not want the
    garbage collection mechanism to kick in. Of course, by turning off the
    garbage collection for certain parts of your application, you do risk
    creating memory leaks because some possible roots might not fit into the
    limited root buffer. Therefore, it is probably wise to call
     <span class="function"><a href="function.gc-collect-cycles.html" class="function">gc_collect_cycles()</a></span> just before you call
     <span class="function"><a href="function.gc-disable.html" class="function">gc_disable()</a></span> to free up the memory that could be lost
    through possible roots that are already recorded in the root buffer. This
    then leaves an empty buffer so that there is more space for storing
    possible roots while the cycle collecting mechanism is turned off.
   </p>
  </div><hr /><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="features.gc.refcounting-basics.html">Reference Counting Basics</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="features.gc.performance-considerations.html">Performance Considerations</a></div>
 <div class="up"><a href="features.gc.html">Garbage Collection</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div></body></html>