Compiling APD for PHP 5.4

APD (Advanced PHP Debugger) is a very useful PHP module for profiling and testing PHP scripts. I don't know why it's not maintained any more and therefore you can't even install it easily using PECL. With PHP 5.4 even more problems occurred and it's really tedious work googling how to fix each of them.

I know, I could use just Xdebug, but I prefer to profile CLI scripts using APD because it's very similar to Python's -m cProfiler and you can quickly check the generated profiles with pprofp.

But at the end I succeed and APD really works with PHP 5.4. Here are a couple of steps (just note that this is for PHP 5.4, it may be different for later versions):

Obtaining APD

  1. Download the latest version of APD from pecl.php.net (it's probably 1.0.1).

  2. Unpack it (in terminal it's for instance tar -xvzf apd-1.0.1.tgz).

Compiling APD

  1. At first just make sure your phpize is the one that comes with PHP 5.4, because you might have more versions of PHP installed on your system and PHP 5.4 probably won't be the default one. So, this is what it looks like when I try phpize -v on PHP 5.4.5:

    Configuring for:
    PHP Api Version:         20100412
    Zend Module Api No:      20100525
    Zend Extension Api No:   220100525

    If you see something like PHP Api Version: 2009XXXX, then you're probably using phpize for PHP 5.3.

  2. Run ./configure

  3. Finally you can run make and see what happens. Probably it will end throwing some warnings and 1-3 errors. (I think 1 error on PHP 5.3 and 3 errors on PHP 5.4)

Fixing APD source code

After running make compilation will probably fail with these errors (tested on PHP 5.4.5, with PHP 5.3 you'll see probably just one error). You can fix all of them manually or by downloading and applyingthis diff file (note: this patch should be compatible with both PHP 5.3 and PHP 5.4).

  • php_apd.c:73:1: error: unknown type name 'function_entry' (PHP 5.4)
    This is documented on stackoverflow.com and bugs.php.net. Just replace line

    function_entry apd_functions[] = {
    with
    zend_function_entry apd_functions[] = {
  • php_apd.c:324:31: error: no member named 'u' in 'union _znode_op' (PHP 5.4)
    Replace this line

    switch (execd->opline->op2.u.constant.value.lval) { 

    with
  • switch (execd->opline->extended_value) {
  • php_apd.c:967:5: error: no member named 'extended_info' in 'struct _zend_compiler_globals' (both PHP 5.4 and PHP 5.3)
    This was probably some kind of temporary solution. Replace

     967  
    CG(extended_info) = 1; /* XXX: this is ridiculous */ 
    with
     967  
    CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; 

If you're familiar with using patch files on unix based systems it's probably easier to download diff file and apply it (this also fixes APD version in php_apd.h:

patch < apd-php54.diff

Testing

Before you can start using APD, run make install. This should copy the compiled .so library into your PHP extensions directory (if it didn't, do it manually). Then just enable it as a zend_extension in yourphp.ini and eventually set apd.dumpdir but it's not necessary.

Just to proof that APD really works we can try some simple PHP script like this

<?php
// apd-test.php

apd_set_pprof_trace('.');
$someArray = array();

function my_test_function($index, $array) {
     if (in_array($index, $array)) {
          // something
     } else {
          // blah
     }
}

for ($i=0; $i < 10000; $i++) {
     my_test_function($i, $someArray);
     $someArray[$i] = true;
}

and run it php apd-test.php. It should create a file in the same directory, something likepprof.SOME_PID.
That's nice, the last thing is to view what it generated. APD comes with script called pprofp, it's maybe a good idea to make a symlink or copy it into your /usr/bin.
Then call pprofp -l pprof.SOME_PID and watch the profiler output:

Trace for /Users/martin/develop/php/apd-test/apd-test.php
Total Elapsed Time = 0.12
Total System Time  = 0.01
Total User Time    = 0.07


         Real         User        System             secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------------------------------------------------------------
71.3 0.06 0.06  0.05 0.05  0.01 0.01  10000  0.0000   0.0000            0 in_array
27.3 0.02 0.09  0.02 0.07  0.00 0.01  10000  0.0000   0.0000            0 my_test_function
 1.5 0.03 0.03  0.00 0.00  0.00 0.00      1  0.0000   0.0000            0 apd_set_pprof_trace
 0.0 0.00 0.12  0.00 0.07  0.00 0.01      1  0.0000   0.0000            0 main

And that's it. You should be good to go with APD on PHP 5.4.

php 5.3 apd-1.0.1:
php_apd.c
-    CG(extended_info) = 1;  /* XXX: this is ridiculous */
+    CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
-ZEND_DLEXPORT void onStatement(zend_op_array *op_array TSRMLS_DC);
+ZEND_DLEXPORT void onStatement(zend_op_array *op_array);
php_apd.h:
-#define APD_VERSION “0.9″
+#define APD_VERSION “1.0.1″
[apd]
zend_extension=/usr/server/phpfpm/lib/php/extensions/no-debug-zts-20090626/apd.so
apd.dumpdir=/tmp
apd.statement_tracing=0


rename_function('unlink', 'debug_unlink');
override_function('unlink', '$filename',
    '$flag = debug_unlink($filename);
    if ($flag) {
         $fp = fopen(“/tmp/delfile.txt”, “ab”);
        fwrite($fp, $filename);
        fclose($fp);
    }
    return $flag;'
);
unlink('/tmp/oktest');
echo 'OK';
exit;
if ( !-f $request_filename ) {
           rewrite ^/([0-9]*)$ /space.php?uid=$1& last;
        }

http://www.linuxjournal.com/article/7213?page=0,1

  • PHP: APD - Advanced PHP debugger
  • How to use PHP-APD in your scripts - APD 使用方式

不過, 太久沒用這工具, 沒想到 APD 從 2008年到現在(2011), 都沒有新版, 使用 Pecl 安裝, 也無法直接安裝完成, 在此順便把解法紀錄於此.

PHP APD 安裝 與 問題排除

  1. sudo apt-get install php-pear # 有 /usr/bin/pecl
  2. sudo apt-get install re2c # apd compile 需要
  3. sudo pecl search apd # http://pecl.php.net/package/apd
  4. sudo pecl install apd # 安裝失敗, 出現下述錯誤

    make: *** [php_apd.lo] Error 1

解法
  1. 詳見: Debian PHP 5.3 APD compile problems
  2. sudo pecl download apd
  3. tar xvf apd-1.0.1.tgz
  4. cd apd-1.0.1/
  5. vim php_apd.c

    # 第 967 行
    GC(extended_info) = 1;
    改成
    CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;

  6. phpize
  7. ./configure
  8. make
  9. make test
  10. sudo make install

    Installing shared extensions: /usr/lib/php5/20090626/

  11. sudo cp pprofp /usr/bin/ # pprofp 是用來分析 profiling 完成後的檔案用

PHP APD 設定

  • vim /etc/php5/conf.d/apd.ini

    zend_extension = /usr/lib/php5/20090626/apd.so
    apd.dumpdir = /tmp
    apd.statement_trace = 0

PHP APD 使用 與 測試

APD 使用方式很簡單, 只要在要 trace 的 script 上面, 加上 "apd_set_pprof_trace();" 就可以了, 詳可見下述範例.

  1. vim script.php # 需在要 trace 得程式上面加上 "apd_set_pprof_trace();"

    <?php
    apd_set_pprof_trace();

    //rest of the script
    $a = '2001-03-01 11:11:12';
    echo substr($a, 0, 4);
    echo substr($a, 5, 2);
    echo substr($a, 8, 2);
    ?>

  2. php -e -f script.php # 也可以直接 php script.php 即可, 會產生類似如此的檔案: "/tmp/pprof.xxxxx"

PHP APD 分析

PHP APD 的 pprofp 請依照自己所需要的參數使用, 會出現類似下述的分析結果.

  • pprofp -u /tmp/pprof.25802
  • pprofp -t /tmp/pprof.15507

    Trace for /tmp/script.php
    Total Elapsed Time = 0.01
    Total System Time  = 0.00
    Total User Time    = 0.00
    Real         User        System             secs/    cumm
    %Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
    --------------------------------------------------------------------------------------
    0.0 0.00 0.00  0.00 0.00  0.00 0.00     3  0.0000   0.0000            0 substr
    0.0 0.01 0.01  0.00 0.00  0.00 0.00     1  0.0000   0.0000            0 apd_set_pprof_trace
    0.0 0.00 0.01  0.00 0.00  0.00 0.00     1  0.0000   0.0000            0 main

相關網頁

  • Simplest way to profile a PHP script
  • PHP Performance Profiling
  • php之debug工具-apd--by 小仙
  • Profiling PHP Applications - nano

你可能感兴趣的:(Compiling APD for PHP 5.4)