diff --git a/.arcconfig b/.arcconfig index 30d1e80d..9e489cb8 100644 --- a/.arcconfig +++ b/.arcconfig @@ -1,6 +1,5 @@ { - "project_id" : "xhprof", - "conduit_uri" : "https://secure.phabricator.com/", - "remote_hooks_installed" : true, - "copyright_holder" : "Facebook, Inc." -} \ No newline at end of file + "phabricator.uri": "https://secure.phabricator.com/", + "load": ["support/libxhprof"], + "unit.engine": "XHProfExtensionUnitTestEngine" +} diff --git a/.arclint b/.arclint new file mode 100644 index 00000000..e141495b --- /dev/null +++ b/.arclint @@ -0,0 +1,30 @@ +{ + "exclude": [ + "(^xhprof_html/jquery/)", + "(^xhprof_html/docs/)", + "(^extension/Makefile.local)" + ], + "linters": { + "chmod": { + "type": "chmod" + }, + "filename": { + "type": "filename" + }, + "generated": { + "type": "generated" + }, + "merge-conflict": { + "type": "merge-conflict" + }, + "nolint": { + "type": "nolint" + }, + "text-without-length": { + "type": "text", + "severity": { + "3": "disabled" + } + } + } +} diff --git a/.gitignore b/.gitignore index e75f3af4..f1631981 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,12 @@ extension/* !extension/php_xhprof.h !extension/tests/ !extension/xhprof.c + +extension/tests/*.sh +extension/tests/*.exp +extension/tests/*.out +extension/tests/*.diff +extension/tests/*.log +extension/tests/*.php + +support/libxhprof/.phutil_module_cache diff --git a/CREDITS b/CREDITS index fd032202..1b9af6b8 100644 --- a/CREDITS +++ b/CREDITS @@ -1,5 +1,7 @@ Originally developed at Facebook, XHProf was open sourced in Mar, 2009. +XHProf is now maintained by Phacility. + Creators: Changhao Jiang Kannan Muthukkaruppan @@ -9,4 +11,3 @@ Creators: Additional Contributors: George Cabrera - UI enhancements Paul Saab - FreeBSD port - diff --git a/LICENSE b/LICENSE index f433b1a5..d9a10c0d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,3 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/README b/README index 309dcfe2..a8c15fa9 100644 --- a/README +++ b/README @@ -3,5 +3,3 @@ For installation and usage notes refer to: To view the latest version of the doc, go to: http://pecl.php.net/package/xhprof ---> [View Documentation] - - diff --git a/bin/xhprofile b/bin/xhprofile new file mode 120000 index 00000000..56da2f66 --- /dev/null +++ b/bin/xhprofile @@ -0,0 +1 @@ +../scripts/xhprofile.php \ No newline at end of file diff --git a/composer.json b/composer.json deleted file mode 100644 index 2efe9628..00000000 --- a/composer.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "facebook/xhprof", - "type": "library", - "description": "XHProf: A Hierarchical Profiler for PHP", - "keywords": ["profiling", "performance"], - "homepage": "http://pecl.php.net/package/xhprof", - "license": "Apache-2.0", - "require": { - "php": ">=5.2.0" - }, - "autoload": { - "files": [ - "xhprof_lib/utils/xhprof_lib.php", - "xhprof_lib/utils/xhprof_runs.php" - ] - } -} diff --git a/extension/config.m4 b/extension/config.m4 index 351786bd..75401474 100644 --- a/extension/config.m4 +++ b/extension/config.m4 @@ -1,4 +1,3 @@ - PHP_ARG_ENABLE(xhprof, whether to enable xhprof support, [ --enable-xhprof Enable xhprof support]) diff --git a/extension/php_xhprof.h b/extension/php_xhprof.h index 42fb23b4..13d914c6 100644 --- a/extension/php_xhprof.h +++ b/extension/php_xhprof.h @@ -42,4 +42,4 @@ PHP_FUNCTION(xhprof_disable); PHP_FUNCTION(xhprof_sample_enable); PHP_FUNCTION(xhprof_sample_disable); -#endif /* PHP_XHPROF_H */ +#endif /* PHP_XHPROF_H */ diff --git a/extension/tests/common.php b/extension/tests/common.php index 23b2f719..f808ff38 100644 --- a/extension/tests/common.php +++ b/extension/tests/common.php @@ -32,4 +32,3 @@ function print_canonical($xhprof_data) { echo "\n"; } } - diff --git a/extension/tests/xhprof_001.phpt b/extension/tests/xhprof_001.phpt index dc14c28c..40d76f02 100644 --- a/extension/tests/xhprof_001.phpt +++ b/extension/tests/xhprof_001.phpt @@ -1,5 +1,5 @@ --TEST-- -XHPRrof: Basic Profiling Test +XHProf: Basic Profiling Test Author: Kannan --FILE-- +$xhprof_ignored_functions = array( 'ignored_functions' => array('call_user_func', 'call_user_func_array', 'my_call_user_func_safe', @@ -20,8 +20,8 @@ function foo($x) { for ($idx = 0; $idx < 2; $idx++) { $sum += bar(); } - echo "hello: {$x}\n" ; - return strlen("hello: {$x}"); + echo @"hello: {$x}\n" ; + return @strlen("hello: {$x}"); } function foo_array($x1, $x2 = 'test') { @@ -30,8 +30,8 @@ function foo_array($x1, $x2 = 'test') { foreach ($x as $idx) { $sum += bar(); } - echo "hello: " . $x[0] . $x[1] . "\n"; - return strlen("hello: {$x[0]} {$x[1]}"); + echo @"hello: {$x[0]}{$x[1]}\n"; + return @strlen("hello: {$x[0]} {$x[1]}"); } function my_call_user_func_safe($function, $args = 'my_safe') { @@ -161,7 +161,7 @@ echo "\n"; // 5c: Sanity test to only ignore my_call_user_func_array_safe echo "Part 5c: Only ignore call_user_func_array\n"; -$xhprof_ignored_functions = array('ignored_functions' => +$xhprof_ignored_functions = array('ignored_functions' => 'my_call_user_func_array_safe'); xhprof_enable(XHPROF_FLAGS_MEMORY, $xhprof_ignored_functions); test_my_call_user_func_array_safe('foo_array'); diff --git a/extension/tests/xhprof_008.phpt b/extension/tests/xhprof_008.phpt index b0f4af57..e62849f1 100644 --- a/extension/tests/xhprof_008.phpt +++ b/extension/tests/xhprof_008.phpt @@ -1,5 +1,5 @@ --TEST-- -XHPRrof: Sampling Mode Test +XHProf: Sampling Mode Test Author: kannan --FILE-- +} + +spl_autoload_register('loader', $throw = true); + +xhprof_enable(); + +class_exists('ThisClassDoesNotExist'); +echo "OK\n"; + +--EXPECT-- +OK diff --git a/extension/tests/xhprof_010.phpt b/extension/tests/xhprof_010.phpt new file mode 100644 index 00000000..33b4a14e --- /dev/null +++ b/extension/tests/xhprof_010.phpt @@ -0,0 +1,16 @@ +--TEST-- +XHProf: Crash with auto_append_file +Author: epriestley +--INI-- +include_path={PWD} +auto_append_file=xhprof_010_append.php +--FILE-- + +--EXPECTF-- +MAIN +APPENDED diff --git a/extension/tests/xhprof_010_append.php b/extension/tests/xhprof_010_append.php new file mode 100644 index 00000000..7e569914 --- /dev/null +++ b/extension/tests/xhprof_010_append.php @@ -0,0 +1,3 @@ + +--EXPECTF-- +PREPENDED +MAIN diff --git a/extension/tests/xhprof_011_prepend.php b/extension/tests/xhprof_011_prepend.php new file mode 100644 index 00000000..22386904 --- /dev/null +++ b/extension/tests/xhprof_011_prepend.php @@ -0,0 +1,4 @@ + array($large))); +xhprof_disable(); +unset($large); + +xhprof_enable(); +xhprof_disable(); + +$new = memory_get_usage(); + +$missing = ($new - $old); + +if ($missing >= (1024 * 1024 * 16)) { + echo "LEAKED A LOT OF MEMORY\n"; +} else { + echo "DID NOT LEAK A LOT OF MEMORY\n"; +} + +?> +--EXPECTF-- +DID NOT LEAK A LOT OF MEMORY diff --git a/extension/xhprof.c b/extension/xhprof.c index f97bcf1d..66aa041e 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -596,6 +596,11 @@ static inline uint8 hp_inline_hash(char * str) { * @author mpal */ static void hp_get_ignored_functions_from_arg(zval *args) { + + if (hp_globals.ignored_function_names) { + hp_array_del(hp_globals.ignored_function_names); + } + if (args != NULL) { zval *zresult = NULL; @@ -961,7 +966,13 @@ static char *hp_get_function_name(zend_op_array *ops TSRMLS_DC) { /* we are dealing with a special directive/function like * include, eval, etc. */ -#if ZEND_EXTENSION_API_NO >= 220100525 +#if ZEND_EXTENSION_API_NO >= 220121212 + if (data->prev_execute_data) { + curr_op = data->prev_execute_data->opline->extended_value; + } else { + curr_op = data->opline->extended_value; + } +#elif ZEND_EXTENSION_API_NO >= 220100525 curr_op = data->opline->extended_value; #else curr_op = data->opline->op2.u.constant.value.lval; @@ -1703,8 +1714,30 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, if (!_zend_execute_internal) { /* no old override to begin with. so invoke the builtin's implementation */ + +#if ZEND_EXTENSION_API_NO >= 220121212 + /* PHP 5.5. This is just inlining a copy of execute_internal(). */ + + if (fci != NULL) { + ((zend_internal_function *) execute_data->function_state.function)->handler( + fci->param_count, + *fci->retval_ptr_ptr, + fci->retval_ptr_ptr, + fci->object_ptr, + 1 TSRMLS_CC); + } else { + zval **return_value_ptr = &EX_TMP_VAR(execute_data, execute_data->opline->result.var)->var.ptr; + ((zend_internal_function *) execute_data->function_state.function)->handler( + execute_data->opline->extended_value, + *return_value_ptr, + (execute_data->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? return_value_ptr + : NULL, + execute_data->object, + ret TSRMLS_CC); + } +#elif ZEND_EXTENSION_API_NO >= 220100525 zend_op *opline = EX(opline); -#if ZEND_EXTENSION_API_NO >= 220100525 temp_variable *retvar = &EX_T(opline->result.var); ((zend_internal_function *) EX(function_state).function)->handler( opline->extended_value, @@ -1713,6 +1746,7 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, &retvar->var.ptr:NULL, EX(object), ret TSRMLS_CC); #else + zend_op *opline = EX(opline); ((zend_internal_function *) EX(function_state).function)->handler( opline->extended_value, EX_T(opline->result.u.var).var.ptr, @@ -2016,4 +2050,3 @@ static inline void hp_array_del(char **name_array) { efree(name_array); } } - diff --git a/package.xml b/package.xml index 478ee25f..59e92a75 100644 --- a/package.xml +++ b/package.xml @@ -50,7 +50,7 @@ XHProf is a function-level hierarchical profiler for PHP and has a simple HTML b macvicar scott@fb.com yes - + 2009-03-28 0.9.2 diff --git a/scripts/xhprofile.php b/scripts/xhprofile.php new file mode 100755 index 00000000..36891e99 --- /dev/null +++ b/scripts/xhprofile.php @@ -0,0 +1,19 @@ +#!/usr/bin/env php +'); +} + +$__xhprof_target__ = $argv[1]; + +$argv = array_slice($argv, 1); +$argc = count($argv); + +xhprof_enable(); +require_once $__xhprof_target__; +$xhprof_data = xhprof_disable(); + +var_dump($xhprof_data); diff --git a/support/libxhprof/__phutil_library_init__.php b/support/libxhprof/__phutil_library_init__.php new file mode 100644 index 00000000..31f0c680 --- /dev/null +++ b/support/libxhprof/__phutil_library_init__.php @@ -0,0 +1,3 @@ + 2, + 'class' => array( + 'XHProfExtensionUnitTestEngine' => 'unit/XHProfUnitTestEngine.php', + ), + 'function' => array(), + 'xmap' => array( + 'XHProfExtensionUnitTestEngine' => 'ArcanistUnitTestEngine', + ), +)); diff --git a/support/libxhprof/unit/XHProfUnitTestEngine.php b/support/libxhprof/unit/XHProfUnitTestEngine.php new file mode 100644 index 00000000..955261a2 --- /dev/null +++ b/support/libxhprof/unit/XHProfUnitTestEngine.php @@ -0,0 +1,53 @@ +getWorkingCopy()->getProjectRoot().'/extension/'; + + $start_time = microtime(true); + + id(new ExecFuture('phpize && ./configure && make -j4')) + ->setCWD($root) + ->resolvex(); + + $out = id(new ExecFuture('make -f Makefile.local test_with_exit_status')) + ->setCWD($root) + ->setEnv( + array( + 'TEST_PHP_ARGS' => '-q', + )) + ->resolvex(); + + // NOTE: REPORT_EXIT_STATUS doesn't seem to work properly in some versions + // of PHP. Just "parse" stdout to approximate the results. + + list($stdout) = $out; + + $tests = array(); + + foreach (phutil_split_lines($stdout) as $line) { + $matches = null; + + // NOTE: The test script writes the name of the test originally, then + // uses "\r" to erase it and write the result. This splits as a single + // line. + if (preg_match('/^TEST .*\r(PASS|FAIL) (.*)/', $line, $matches)) { + if ($matches[1] == 'PASS') { + $result = ArcanistUnitTestResult::RESULT_PASS; + } else { + $result = ArcanistUnitTestResult::RESULT_FAIL; + } + + $name = trim($matches[2]); + + $tests[] = id(new ArcanistUnitTestResult()) + ->setName($name) + ->setResult($result) + ->setDuration(microtime(true) - $start_time); + } + } + + return $tests; + } +} diff --git a/xhprof_html/css/xhprof.css b/xhprof_html/css/xhprof.css index 88933db3..c3abf862 100644 --- a/xhprof_html/css/xhprof.css +++ b/xhprof_html/css/xhprof.css @@ -79,4 +79,3 @@ ul.xhprof_actions li a:hover { background:#3B5998 none repeat scroll 0 0; color:#FFFFFF; } - diff --git a/xhprof_lib/display/typeahead_common.php b/xhprof_lib/display/typeahead_common.php index 7b1098f4..0cd304d6 100644 --- a/xhprof_lib/display/typeahead_common.php +++ b/xhprof_lib/display/typeahead_common.php @@ -77,4 +77,3 @@ foreach ($functions as $f) { echo $f."\n"; } - diff --git a/xhprof_lib/display/xhprof.php b/xhprof_lib/display/xhprof.php index 4be67bc8..a57ec175 100644 --- a/xhprof_lib/display/xhprof.php +++ b/xhprof_lib/display/xhprof.php @@ -1003,7 +1003,7 @@ function print_pc_array($url_params, $results, $base_ct, $base_info, $parent, function print_source_link($info) { if (strncmp($info['fn'], 'run_init', 8) && $info['fn'] !== 'main()') { - if (defined('XHPROF_SYMBOL_LOOKUP_URL')) { + if (defined('XHPROF_SYMBOL_LOOKUP_URL')) { $link = xhprof_render_link( 'source', XHPROF_SYMBOL_LOOKUP_URL . '?symbol='.rawurlencode($info["fn"])); diff --git a/xhprof_lib/utils/xhprof_lib.php b/xhprof_lib/utils/xhprof_lib.php index 1e398a9d..4a07e900 100644 --- a/xhprof_lib/utils/xhprof_lib.php +++ b/xhprof_lib/utils/xhprof_lib.php @@ -943,4 +943,3 @@ function xhprof_get_matching_functions($q, $xhprof_data) { return ($res); } - diff --git a/xhprof_lib/utils/xhprof_runs.php b/xhprof_lib/utils/xhprof_runs.php index cde5ff55..2a22a5dc 100644 --- a/xhprof_lib/utils/xhprof_runs.php +++ b/xhprof_lib/utils/xhprof_runs.php @@ -95,8 +95,7 @@ public function __construct($dir = null) { $dir = ini_get("xhprof.output_dir"); if (empty($dir)) { - // some default that at least works on unix... - $dir = "/tmp"; + $dir = sys_get_temp_dir(); xhprof_error("Warning: Must specify directory location for XHProf runs. ". "Trying {$dir} as default. You can either pass the " .