Matt Gibson
Matt Gibson

Reputation: 14949

How can I use XHProf to profile PHPUnit tests from the command line?

I have some very slow PHPUnit tests (8 mins for 43 tests) and I need to use XHProf to find out what is going wrong.

How can I do this from the command line? I have PHPUnit in the project's /vendor directory, loaded via composer.

Upvotes: 10

Views: 3951

Answers (3)

bishop
bishop

Reputation: 39414

Supplementing @Gordon's answer regarding xhprof.

There are two parts:

  1. The PECL extension
  2. The user-space viewer

The PECL extension adds methods to the PHP engine for metrics collection. You must install this extension.

The user-space viewer provides a web interface for understanding the output of the metrics collection. You don't need this, but you really want it. Unless you enjoy looking at raw metric data. To install and configure the user-space viewer so that PHPUnit can profile your tests:

(1) Add these packages to your composer.json:

composer require "facebook/xhprof:dev-master@dev" --dev
composer require "phpunit/test-listener-xhprof:1.0.*@dev" --dev

(2) Configure your web server to serve the vendor/facebook/xhprof/xhprof_html/ directory. Remember the URL.

(3) Adapt your existing PHPUnit configuration into a phpunit-xhprof.xml that's similar to this. Make sure you change the "appNamespace" to match your code and change "xhprofWeb" to the URL from step 2:

<phpunit>
  <testsuites>
    <testsuite name="All Tests">
      <directory suffix="Test.php">tests/</directory>
    </testsuite>
  </testsuites>
  <listeners>
    <listener class="PHPUnit\XHProfTestListener\XHProfTestListener" file="vendor/phpunit/test-listener-xhprof/src/XHProfTestListener.php">
     <arguments>
      <array>
       <element key="appNamespace">
        <string>App</string>
       </element>
       <element key="xhprofWeb">
        <string>http://localhost/vendor/facebook/xhprof/xhprof_html/index.php</string>
       </element>
       <element key="xhprofLibFile">
        <string>./vendor/facebook/xhprof/xhprof_lib/utils/xhprof_lib.php</string>
       </element>
       <element key="xhprofRunsFile">
        <string>./vendor/facebook/xhprof/xhprof_lib/utils/xhprof_runs.php</string>
       </element>
       <element key="xhprofFlags">
        <string>XHPROF_FLAGS_CPU,XHPROF_FLAGS_MEMORY</string>
       </element>
       <element key="xhprofIgnore">
        <string>call_user_func,call_user_func_array</string>
       </element>
      </array>
     </arguments>
    </listener>
   </listeners>
</phpunit>

(4) Run PHP and collect statistics: phpunit -c ./phpunit-xhprof.xml

You'll see output similar to the following:

 * BishopB\Pattern\Exception\InvalidArgumentTest::test_hierarchy
   http://localhost/vendor/facebook/xhprof/xhprof_html/index.php?run=556e05cec844c&source=BishopB\Pattern

That's the URL you configured to view the result of the run. If you want to view the raw metrics data, find that run key ("556e05cec844c", in this example) in your temporary directory:

$ ls -l /tmp/556e05cec844c.BishopB\\Pattern.xhprof
-rw-rw-r-- 1 bishop staff 16963 Jun  2 15:36 /tmp/556e05cec844c.BishopB\Pattern.xhprof

Upvotes: 4

Gordon
Gordon

Reputation: 316999

To find out which test are running slow, you can use

Install the Listener via Composer and then enable it in your phpunit.xml, e.g.

<phpunit bootstrap="vendor/autoload.php">
...
    <listeners>
        <listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" />
    </listeners>
</phpunit>

To find out why tests are running slow, you can use

You can configure it in phpunit.xml, e.g.

 <listeners>
  <listener class="PHPUnit_Util_Log_XHProf" file="PHPUnit/Util/Log/XHProf.php">
   <arguments>
    <array>
     <element key="xhprofLibFile">
      <string>/var/www/xhprof_lib/utils/xhprof_lib.php</string>
     </element>
     <element key="xhprofRunsFile">
      <string>/var/www/xhprof_lib/utils/xhprof_runs.php</string>
     </element>
     <element key="xhprofWeb">
      <string>http://localhost/xhprof_html/index.php</string>
     </element>
     <element key="appNamespace">
      <string>Doctrine2</string>
     </element>
     <element key="xhprofFlags">
      <string>XHPROF_FLAGS_CPU,XHPROF_FLAGS_MEMORY</string>
     </element>
     <element key="xhprofIgnore">
      <string>call_user_func,call_user_func_array</string>
     </element>
    </array>
   </arguments>
  </listener>
 </listeners>

Upvotes: 11

MikeD
MikeD

Reputation: 382

Make sure you have added the xdebug lines to your cli php.ini, not just the apache php.ini. On Ubuntu its at /etc/php5/cli/php.ini. You should add these lines to the file: zend_extension=/usr/lib/php5/20100525+lfs/xdebug.so xdebug.profiler_enable=1 xdebug.profiler_output_dir=/path/to/output_dir xdebug.profiler_output_name=cachegrind.out.%R.%t

EDIT: Oops, you are right, I was thinking of using cachegrind. The lines to add would be below, but my main point is the same. Make sure you take a look at the cli php.ini.

[xhprof]
extension=xhprof.so
xhprof.output_dir="/var/tmp/xhprof"

Upvotes: 0

Related Questions