Sophie

Sophie

distrib > Mageia > 4 > i586 > by-pkgid > f800694edefe91adea2624f711a41a2d > files > 1906

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>Performance Considerations</title>

 </head>
 <body><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="features.gc.collecting-cycles.html">Collecting Cycles</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="features.dtrace.html">DTrace Dynamic Tracing</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.performance-considerations" class="sect1">
   <h2 class="title">Performance Considerations</h2>
   <p class="para">
    We have already mentioned in the previous section that simply collecting the
    possible roots had a very tiny performance impact, but this is when you
    compare PHP 5.2 against PHP 5.3. Although the recording of possible roots
    compared to not recording them at all, like in PHP 5.2, is slower, other
    changes to the PHP runtime in PHP 5.3 prevented this particular performance
    loss from even showing.
   </p>
   <p class="para">
    There are two major areas in which performance is affected. The first
    area is reduced memory usage, and the second area is run-time delay when
    the garbage collection mechanism performs its memory cleanups. We will
    look at both of those issues.
   </p>

   <div class="sect2" id="features.gc.performance-considerations.reduced-mem">
    <h3 class="title">Reduced Memory Usage</h3>
    <p class="para">
     First of all, the whole reason for implementing the garbage collection
     mechanism is to reduce memory usage by cleaning up circular-referenced
     variables as soon as the prerequisites are fulfilled. In PHP&#039;s
     implementation, this happens as soon as the root-buffer is full, or when
     the function  <span class="function"><a href="function.gc-collect-cycles.html" class="function">gc_collect_cycles()</a></span> is called. In
     the graph below, we display the memory usage of the script below,
     in both PHP 5.2 and PHP 5.3, excluding the base memory that PHP
     itself uses when starting up.
    </p>
    <p class="para">
     <div class="example" id="example-396">
      <p><strong>Example #1 Memory usage example</strong></p>
      <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">Foo<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">$var&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'3.1415962654'</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$baseMemory&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">memory_get_usage</span><span style="color: #007700">();<br /><br />for&nbsp;(&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">&lt;=&nbsp;</span><span style="color: #0000BB">100000</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">++&nbsp;)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">Foo</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">self&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$a</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">%&nbsp;</span><span style="color: #0000BB">500&nbsp;</span><span style="color: #007700">===&nbsp;</span><span style="color: #0000BB">0&nbsp;</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #0000BB">sprintf</span><span style="color: #007700">(&nbsp;</span><span style="color: #DD0000">'%8d:&nbsp;'</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">),&nbsp;</span><span style="color: #0000BB">memory_get_usage</span><span style="color: #007700">()&nbsp;-&nbsp;</span><span style="color: #0000BB">$baseMemory</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
      </div>

      <div class="mediaobject">
       
       <div class="imageobject">
        <img src="images/12f37b1c6963c1c5c18f30495416a197-gc-benchmark.png" alt="Comparison of memory usage between PHP 5.2 and PHP 5.3" width="850" height="480" />
       </div>
      </div>
     </div>
    </p>
    <p class="para">
     In this very academic example, we are creating an object in which a
     property is set to point back to the object itself. When the <var class="varname"><var class="varname">$a</var></var> variable
     in the script is re-assigned in the next iteration of the loop, a memory
     leak would typically occur. In this case, two zval-containers are leaked
     (the object zval, and the property zval), but only one possible root is
     found: the variable that was unset. When the root-buffer is full after
     10,000 iterations (with a total of 10,000 possible roots), the garbage
     collection mechanism kicks in and frees the memory associated with those
     possible roots. This can very clearly be seen in the jagged memory-usage
     graph for PHP 5.3. After each 10,000 iterations, the mechanism kicks in
     and frees the memory associated with the circular referenced variables.
     The mechanism itself does not have to do a whole lot of work in this
     example, because the structure that is leaked is extremely simple. From
     the diagram, you see that the maximum memory usage in PHP 5.3 is about 9
     Mb, whereas in PHP 5.2 the memory usage keeps increasing.
    </p>
   </div>

   <div class="sect2" id="features.gc.performance-considerations.slowdowns">
    <h3 class="title">Run-Time Slowdowns</h3>
    <p class="para">
     The second area where the garbage collection mechanism influences
     performance is the time taken when the garbage collection mechanism
     kicks in to free the &quot;leaked&quot; memory. In order to see how much this is,
     we slightly modify the previous script to allow for a larger number of
     iterations and the removal of the intermediate memory usage figures. The
     second script is here:
    </p>
    <p class="para">
     <div class="example" id="example-397">
      <p><strong>Example #2 GC performance influences</strong></p>
      <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">Foo<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">$var&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'3.1415962654'</span><span style="color: #007700">;<br />}<br /><br />for&nbsp;(&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">&lt;=&nbsp;</span><span style="color: #0000BB">1000000</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">++&nbsp;)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">Foo</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">self&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$a</span><span style="color: #007700">;<br />}<br /><br />echo&nbsp;</span><span style="color: #0000BB">memory_get_peak_usage</span><span style="color: #007700">(),&nbsp;</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
      </div>

     </div>
    </p>
    <p class="para">
     We will run this script two times, once with the
     <a href="info.configuration.html#ini.zend.enable-gc" class="link">zend.enable_gc</a> setting turned
     on, and once with it turned off:
    </p>
    <p class="para">
     <div class="example" id="example-398">
      <p><strong>Example #3 Running the above script</strong></p>
      <div class="example-contents">
<div class="shellcode"><pre class="shellcode">time php -dzend.enable_gc=0 -dmemory_limit=-1 -n example2.php
# and
time php -dzend.enable_gc=1 -dmemory_limit=-1 -n example2.php</pre>
</div>
      </div>

     </div>
    </p>
    <p class="para">
     On my machine, the first command seems to take consistently about 10.7
     seconds, whereas the second command takes about 11.4 seconds. This is a
     slowdown of about 7%. However, the maximum amount of memory used by the
     script is reduced by 98% from 931Mb to 10Mb. This benchmark is not very
     scientific, or even representative of real-life applications, but it
     does demonstrate the memory usage benefits that this garbage collection
     mechanism provides. The good thing is that the slowdown is always the
     same 7%, for this particular script, while the memory saving
     capabilities save more and more memory as more circular references are
     found during script execution.
    </p>
   </div>

   <div class="sect2" id="features.gc.performance-considerations.internal-stats">
    <h3 class="title">PHP&#039;s Internal GC Statistics</h3>
    <p class="para">
     It is possible to coax a little bit more information about how the
     garbage collection mechanism is run from within PHP. But in order to do
     so, you will have to re-compile PHP to enable the benchmark and
     data-collecting code. You will have to set the <em>CFLAGS</em>
     environment variable to <em>-DGC_BENCH=1</em> prior to running
     <em>./configure</em> with your desired options. The following
     sequence should do the trick:
    </p>
    <p class="para">
     <div class="example" id="example-399">
      <p><strong>Example #4 Recompiling PHP to enable GC benchmarking</strong></p>
      <div class="example-contents">
<div class="shellcode"><pre class="shellcode">export CFLAGS=-DGC_BENCH=1
./config.nice
make clean
make</pre>
</div>
      </div>

     </div>
    </p>
    <p class="para">
     When you run the above example code again with the newly built PHP
     binary, you will see the following being shown after PHP has finished
     execution:
    </p>
    <p class="para">
     <div class="example" id="example-400">
      <p><strong>Example #5 GC statistics</strong></p>
      <div class="example-contents">
<div class="shellcode"><pre class="shellcode">GC Statistics
-------------
Runs:               110
Collected:          2072204
Root buffer length: 0
Root buffer peak:   10000

      Possible            Remove from  Marked
        Root    Buffered     buffer     grey
      --------  --------  -----------  ------
ZVAL   7175487   1491291    1241690   3611871
ZOBJ  28506264   1527980     677581   1025731</pre>
</div>
      </div>

     </div>
    </p>
    <p class="para">
     The most informative statistics are displayed in the first block. You
     can see here that the garbage collection mechanism ran 110 times, and in
     total, more than 2 million memory allocations were freed during those
     110 runs. As soon as the garbage collection mechanism has run at least
     one time, the &quot;Root buffer peak&quot; is always 10000.
    </p>
   </div>

   <div class="sect2" id="features.gc.performance-considerations.conclusion">
    <h3 class="title">Conclusion</h3>
    <p class="para">
     In general the garbage collector in PHP will only cause a slowdown when the
     cycle collecting algorithm actually runs, whereas in normal (smaller)
     scripts there should be no performance hit at all.
    </p>
    <p class="para">
     However, in the cases where the cycle collection mechanism does run for
     normal scripts, the memory reduction it will provide allows more of
     those scripts to run concurrently on your server, since not so much
     memory is used in total.
    </p>
    <p class="para">
     The benefits are most apparent for longer-running scripts, such as
     lengthy test suites or daemon scripts. Also, for <a href="http://gtk.php.net/" class="link external">&raquo;&nbsp;PHP-GTK</a> applications
     that generally tend to run longer than scripts for the Web, the new
     mechanism should make quite a bit of a difference regarding memory leaks
     creeping in over time.
    </p>
   </div>
  </div><hr /><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="features.gc.collecting-cycles.html">Collecting Cycles</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="features.dtrace.html">DTrace Dynamic Tracing</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>