From e3df210a649bed95114e03bc43e720e25b20f0e9 Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 27 Aug 2014 11:31:33 -0700 Subject: [PATCH 01/45] Remove Composer support from XHProf Summary: See . This is currently broken and extremely insecure. We may want to restore it eventually, but understanding composer is very complex (no one who touched this realized that the package was owned by someone unrelated to the project who can apparently redirect it at will with no accountability). No one on the ticket seems to have any reason why this isn't totally wide open, and I haven't gotten in touch with anyone in `#composer-dev`. Test Plan: N/A Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10365 --- composer.json | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 composer.json 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" - ] - } -} From 6065346905d469cefe4f2c621da6bb779f65b081 Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 27 Aug 2014 11:31:39 -0700 Subject: [PATCH 02/45] Update .arcconfig and acknowledge that we're the new maintainers in XHProf Summary: Modernize this stuff a bit. Test Plan: Ran `arc diff` to produce this diff. Read `CREDITS`. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10366 --- .arcconfig | 7 ++----- CREDITS | 3 ++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.arcconfig b/.arcconfig index 30d1e80d..783f1d23 100644 --- a/.arcconfig +++ b/.arcconfig @@ -1,6 +1,3 @@ { - "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/" +} 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 - From 28d18dd1d4f87544c551ba53ff8d5dcca3d52d5e Mon Sep 17 00:00:00 2001 From: Johnson Page Date: Thu, 28 Aug 2014 10:11:57 +1000 Subject: [PATCH 03/45] Fix mismatched tag in contacts Summary: See . Reviewed by: epriestley --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 7adedecdba3f7e89c55bc2ad153aadc6157c5f62 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 28 Aug 2014 10:33:38 -0700 Subject: [PATCH 04/45] XHProf: add .arclint, fix some minor issues Summary: Add a .arclint file and fix some stray tabs and whitespace issues. Test Plan: Built xhprof, ran tests (some failures, but preexisting). Reviewers: chad, btrahan Reviewed By: btrahan Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10372 --- .arclint | 30 +++++++++++++++++++++++++ .gitignore | 7 ++++++ LICENSE | 1 - README | 2 -- extension/config.m4 | 1 - extension/php_xhprof.h | 2 +- extension/tests/common.php | 1 - extension/xhprof.c | 1 - xhprof_html/css/xhprof.css | 1 - xhprof_lib/display/typeahead_common.php | 1 - xhprof_lib/display/xhprof.php | 2 +- xhprof_lib/utils/xhprof_lib.php | 1 - 12 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 .arclint 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..0b8f03db 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,10 @@ 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 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/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/xhprof.c b/extension/xhprof.c index f97bcf1d..7ce3f49d 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -2016,4 +2016,3 @@ static inline void hp_array_del(char **name_array) { efree(name_array); } } - 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); } - From a39446cf68f396413ba838276a4c6b97ad2f89ed Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 28 Aug 2014 10:34:11 -0700 Subject: [PATCH 05/45] Add a basic `arc unit` test binding to XHProf Summary: This allows "arc unit" to more-or-less run the PHP extension tests in an approximately correct way. Note that there are two test failures at HEAD on recent PHP, and they've been failing for some time. Test Plan: Used `arc unit` to run some tests. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10373 --- .arcconfig | 4 +- .gitignore | 2 + support/libxhprof/__phutil_library_init__.php | 3 ++ support/libxhprof/__phutil_library_map__.php | 18 +++++++ .../libxhprof/unit/XHProfUnitTestEngine.php | 53 +++++++++++++++++++ 5 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 support/libxhprof/__phutil_library_init__.php create mode 100644 support/libxhprof/__phutil_library_map__.php create mode 100644 support/libxhprof/unit/XHProfUnitTestEngine.php diff --git a/.arcconfig b/.arcconfig index 783f1d23..9e489cb8 100644 --- a/.arcconfig +++ b/.arcconfig @@ -1,3 +1,5 @@ { - "phabricator.uri": "https://secure.phabricator.com/" + "phabricator.uri": "https://secure.phabricator.com/", + "load": ["support/libxhprof"], + "unit.engine": "XHProfExtensionUnitTestEngine" } diff --git a/.gitignore b/.gitignore index 0b8f03db..f1631981 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ extension/tests/*.out extension/tests/*.diff extension/tests/*.log extension/tests/*.php + +support/libxhprof/.phutil_module_cache 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; + } +} From d8ca30af371e5eeeea7bf37220a8264e61f63422 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 28 Aug 2014 10:34:21 -0700 Subject: [PATCH 06/45] Add a failing test case for the XHProf PHP 5.5 segfault Summary: This adds a failing test case for the bug discussed in . It also adds a `bin/xhprofile` script which makes it easier to test stuff like this, by invoking the profiler on some other script. This isn't hugely useful in production but is valuable diagnostically, and helped me reduce this test case. Test Plan: - Ran `arc unit` and got a failure. - Verified that this test passes if `class_exists()` is commented out (which makes the test not segfault). Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10374 --- bin/xhprofile | 1 + extension/tests/xhprof_009.phpt | 19 +++++++++++++++++++ scripts/xhprofile.php | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 120000 bin/xhprofile create mode 100644 extension/tests/xhprof_009.phpt create mode 100755 scripts/xhprofile.php 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/extension/tests/xhprof_009.phpt b/extension/tests/xhprof_009.phpt new file mode 100644 index 00000000..9e1a55c6 --- /dev/null +++ b/extension/tests/xhprof_009.phpt @@ -0,0 +1,19 @@ +--TEST-- +XHPRrof: PHP 5.5 crash in hp_execute_internal +Author: epriestley +--FILE-- + +} + +spl_autoload_register('loader', $throw = true); + +xhprof_enable(); + +class_exists('ThisClassDoesNotExist'); +echo "OK\n"; + +--EXPECT-- +OK 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); From 55a47c0d8ffeea4b84133fd21103caa816676b5d Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 28 Aug 2014 10:34:42 -0700 Subject: [PATCH 07/45] Fix XHProf segfault when calling internal functions in PHP 5.5 Summary: Fixes . Since the issue with that patch was CLA, I developed this independently. This works because it just inlines the body of `execute_internal()`, which is nearly identical: ``` ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC) { if(fci != NULL) { ((zend_internal_function *) execute_data_ptr->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_ptr, execute_data_ptr->opline->result.var)->var.ptr; ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, (execute_data_ptr->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC); } } ``` Test Plan: Failing test now passes. No more segfaults on PHP 5.5.8. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10375 --- extension/xhprof.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 7ce3f49d..537b9e46 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -1703,8 +1703,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 +1735,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, From 91e0be91da03ec4aa2b63a991f70c1c10151cc71 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 28 Aug 2014 10:34:52 -0700 Subject: [PATCH 08/45] Fix broken XHProf unit tests Summary: There are two broken tests. One (007) is easy to fix. It was failing because of array-to-string conversion warnings. Since I didn't want to add function calls because that would change the test output, I just silenced the warnings with "@". The other test (004) was also easy to fix but I can't really explain what's going on there. Seems like it works though? It shouldn't do anything bad, since we would have generated a meaningless "???_op" otherwise. Test Plan: Ran tests, tests passed. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D10376 --- extension/tests/xhprof_007.phpt | 12 ++++++------ extension/xhprof.c | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/extension/tests/xhprof_007.phpt b/extension/tests/xhprof_007.phpt index d1f26d60..f0fd7302 100644 --- a/extension/tests/xhprof_007.phpt +++ b/extension/tests/xhprof_007.phpt @@ -6,7 +6,7 @@ Author: mpal include_once dirname(__FILE__).'/common.php'; -$xhprof_ignored_functions = array( 'ignored_functions' => +$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/xhprof.c b/extension/xhprof.c index 537b9e46..d213f5cc 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -961,7 +961,9 @@ 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 + curr_op = data->prev_execute_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; From fdd10ab307aed1526ed2982a7c31224fc6fe1663 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 26 Feb 2015 05:56:16 -0800 Subject: [PATCH 09/45] Add a failing test for crashes during auto_append_file See . --- extension/tests/xhprof_010.phpt | 16 ++++++++++++++++ extension/tests/xhprof_010_append.php | 3 +++ 2 files changed, 19 insertions(+) create mode 100644 extension/tests/xhprof_010.phpt create mode 100644 extension/tests/xhprof_010_append.php 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 @@ + Date: Thu, 26 Feb 2015 05:56:16 -0800 Subject: [PATCH 10/45] Add a failing test for auto_prepend_file See . --- extension/tests/xhprof_011.phpt | 15 +++++++++++++++ extension/tests/xhprof_011_prepend.php | 4 ++++ 2 files changed, 19 insertions(+) create mode 100644 extension/tests/xhprof_011.phpt create mode 100644 extension/tests/xhprof_011_prepend.php diff --git a/extension/tests/xhprof_011.phpt b/extension/tests/xhprof_011.phpt new file mode 100644 index 00000000..4021243d --- /dev/null +++ b/extension/tests/xhprof_011.phpt @@ -0,0 +1,15 @@ +--TEST-- +XHProf: Crash with auto_prepend_file +Author: epriestley +--INI-- +include_path={PWD} +auto_prepend_file=xhprof_011_prepend.php +--FILE-- + +--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 @@ + Date: Thu, 26 Feb 2015 06:13:21 -0800 Subject: [PATCH 11/45] Fix segfaults with auto_prepend_file and auto_append_file See: - - --- extension/xhprof.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index d213f5cc..eeb57bb2 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -962,7 +962,11 @@ static char *hp_get_function_name(zend_op_array *ops TSRMLS_DC) { * include, eval, etc. */ #if ZEND_EXTENSION_API_NO >= 220121212 - curr_op = data->prev_execute_data->opline->extended_value; + 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 From 4dbb1aa774ab43ded0a35c8102cdfc2a4f361a42 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 26 Feb 2015 06:20:38 -0800 Subject: [PATCH 12/45] Fix misspelling of "XHProf" as "XHPRrof" in several tests --- extension/tests/xhprof_001.phpt | 2 +- extension/tests/xhprof_002.phpt | 2 +- extension/tests/xhprof_003.phpt | 2 +- extension/tests/xhprof_004.phpt | 2 +- extension/tests/xhprof_005.phpt | 2 +- extension/tests/xhprof_006.phpt | 2 +- extension/tests/xhprof_007.phpt | 2 +- extension/tests/xhprof_008.phpt | 4 ++-- extension/tests/xhprof_009.phpt | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) 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-- Date: Thu, 26 Feb 2015 06:28:59 -0800 Subject: [PATCH 13/45] Add a test case for a memory leak in xhprof_enable() See . --- extension/tests/xhprof_012.phpt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 extension/tests/xhprof_012.phpt diff --git a/extension/tests/xhprof_012.phpt b/extension/tests/xhprof_012.phpt new file mode 100644 index 00000000..ef815e47 --- /dev/null +++ b/extension/tests/xhprof_012.phpt @@ -0,0 +1,32 @@ +--TEST-- +XHProf: Memory Leak in Ignored Functions +Author: epriestley +--FILE-- + 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 From ff8b3892d0cfc53e744631ff5c6b34f13421edce Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 26 Feb 2015 06:32:07 -0800 Subject: [PATCH 14/45] Fix a memory leak in the ignored function list See: - - --- extension/xhprof.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extension/xhprof.c b/extension/xhprof.c index eeb57bb2..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; From 0bbf2a2ac34f495e42aa852293fe0ed821659047 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 26 Feb 2015 06:37:51 -0800 Subject: [PATCH 15/45] Use sys_get_temp_dir(), not hardcoded "/tmp" See: --- xhprof_lib/utils/xhprof_runs.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 " . From 1a3d58dc4a1f181272bcbe3d384a35a6bdea32e6 Mon Sep 17 00:00:00 2001 From: sunan <327369214@qq.com> Date: Thu, 23 Jul 2015 00:07:16 +0800 Subject: [PATCH 16/45] php7 support. not finished --- extension/xhprof.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 66aa041e..ae904aac 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -933,10 +933,10 @@ static char *hp_get_function_name(zend_op_array *ops TSRMLS_DC) { if (data) { /* shared meta data for function on the call stack */ - curr_func = data->function_state.function; + curr_func = data->func; /* extract function name from the meta info */ - func = curr_func->common.function_name; + func = curr_func->common.function_name->val; if (func) { /* previously, the order of the tests in the "if" below was @@ -947,9 +947,9 @@ static char *hp_get_function_name(zend_op_array *ops TSRMLS_DC) { * of the object. */ if (curr_func->common.scope) { - cls = curr_func->common.scope->name; - } else if (data->object) { - cls = Z_OBJCE(*data->object)->name; + cls = curr_func->common.scope->name->val; + } else if (data->called_scope) { + cls = data->called_scope->name->val; } if (cls) { @@ -1010,7 +1010,7 @@ static char *hp_get_function_name(zend_op_array *ops TSRMLS_DC) { if (add_filename){ const char *filename; int len; - filename = hp_get_base_filename((curr_func->op_array).filename); + filename = hp_get_base_filename((curr_func->op_array).filename->val); len = strlen("run_init") + strlen(filename) + 3; ret = (char *)emalloc(len); snprintf(ret, len, "run_init::%s", filename); @@ -1082,7 +1082,7 @@ static void hp_fast_free_hprof_entry(hp_entry_t *p) { * @return void * @author kannan */ -void hp_inc_count(zval *counts, char *name, long count TSRMLS_DC) { +void hp_inc_count(zval *counts, zend_string *name, long count TSRMLS_DC) { HashTable *ht; void *data; @@ -1090,10 +1090,10 @@ void hp_inc_count(zval *counts, char *name, long count TSRMLS_DC) { ht = HASH_OF(counts); if (!ht) return; - if (zend_hash_find(ht, name, strlen(name) + 1, &data) == SUCCESS) { + if (zend_hash_find(ht, name) == SUCCESS) { ZVAL_LONG(*(zval**)data, Z_LVAL_PP((zval**)data) + count); } else { - add_assoc_long(counts, name, count); + add_assoc_long(counts, name->val, count); } } @@ -1114,7 +1114,7 @@ zval * hp_hash_lookup(char *symbol TSRMLS_DC) { } /* Lookup our hash table */ - if (zend_hash_find(ht, symbol, strlen(symbol) + 1, &data) == SUCCESS) { + if (zend_hash_find(ht, zend_string_init(symbol, strlen(symbol) + 1, 0)) == SUCCESS) { /* Symbol already exists */ counts = *(zval **) data; } @@ -1575,9 +1575,9 @@ zval * hp_mode_shared_endfn_cb(hp_entry_t *top, } /* Bump stats in the counts hashtable */ - hp_inc_count(counts, "ct", 1 TSRMLS_CC); + hp_inc_count(counts, zend_string_init("ct", sizeof("ct") - 1, 0), 1 TSRMLS_CC); - hp_inc_count(counts, "wt", get_us_from_tsc(tsc_end - top->tsc_start, + hp_inc_count(counts, zend_string_init("wt", sizeof("wt") - 1, 0), get_us_from_tsc(tsc_end - top->tsc_start, hp_globals.cpu_frequencies[hp_globals.cur_cpu_id]) TSRMLS_CC); return counts; } @@ -1607,7 +1607,7 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { getrusage(RUSAGE_SELF, &ru_end); /* Bump CPU stats in the counts hashtable */ - hp_inc_count(counts, "cpu", (get_us_interval(&(top->ru_start_hprof.ru_utime), + hp_inc_count(counts, zend_string_init("cpu", sizeof("cpu") - 1, 0), (get_us_interval(&(top->ru_start_hprof.ru_utime), &(ru_end.ru_utime)) + get_us_interval(&(top->ru_start_hprof.ru_stime), &(ru_end.ru_stime))) @@ -1620,8 +1620,9 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { pmu_end = zend_memory_peak_usage(0 TSRMLS_CC); /* Bump Memory stats in the counts hashtable */ - hp_inc_count(counts, "mu", mu_end - top->mu_start_hprof TSRMLS_CC); - hp_inc_count(counts, "pmu", pmu_end - top->pmu_start_hprof TSRMLS_CC); + + hp_inc_count(counts, zend_string_init("mu", sizeof("mu") - 1, 0), mu_end - top->mu_start_hprof TSRMLS_CC); + hp_inc_count(counts, zend_string_init("pmu", sizeof("pmu") - 1, 0), pmu_end - top->pmu_start_hprof TSRMLS_CC); } } @@ -1961,13 +1962,13 @@ static zval *hp_zval_at_key(char *key, zval *values) { zval *result = NULL; - if (values->type == IS_ARRAY) { + if (Z_TYPE_P(values) == IS_ARRAY) { HashTable *ht; zval **value; uint len = strlen(key) + 1; ht = Z_ARRVAL_P(values); - if (zend_hash_find(ht, key, len, (void**)&value) == SUCCESS) { + if (zend_hash_find(ht, zend_string_init(key, len, 0)) == SUCCESS) { result = *value; } } else { @@ -1991,7 +1992,7 @@ static char **hp_strings_in_zval(zval *values) { return NULL; } - if (values->type == IS_ARRAY) { + if (Z_TYPE_P(values) == IS_ARRAY) { HashTable *ht; ht = Z_ARRVAL_P(values); @@ -2022,7 +2023,7 @@ static char **hp_strings_in_zval(zval *values) { } } } - } else if(values->type == IS_STRING) { + } else if(Z_TYPE_P(values) == IS_STRING) { if((result = (char**)emalloc(sizeof(char*) * 2)) == NULL) { return result; } From fbb89a9c534d42914cc97f835a9b1b1437d6958b Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 17 Aug 2015 21:15:34 +0800 Subject: [PATCH 17/45] unfinished --- extension/xhprof.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index ae904aac..00b45d81 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -666,7 +666,8 @@ void hp_init_profiler_state(int level TSRMLS_DC) { zval_dtor(hp_globals.stats_count); FREE_ZVAL(hp_globals.stats_count); } - MAKE_STD_ZVAL(hp_globals.stats_count); + + hp_globals.stats_count = (zval *)emalloc(sizeof(zval)); array_init(hp_globals.stats_count); /* NOTE(cjiang): some fields such as cpu_frequencies take relatively longer @@ -1177,8 +1178,7 @@ void hp_sample_stack(hp_entry_t **entries TSRMLS_DC) { add_assoc_string(hp_globals.stats_count, key, - symbol, - 1); + symbol); return; } @@ -1654,7 +1654,7 @@ void hp_mode_sampled_endfn_cb(hp_entry_t **entries TSRMLS_DC) { ZEND_DLEXPORT void hp_execute (zend_op_array *ops TSRMLS_DC) { #else ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { - zend_op_array *ops = execute_data->op_array; + zend_op_array *ops = &execute_data->func->op_array; #endif char *func = NULL; int hp_profile_flag = 1; @@ -1707,7 +1707,7 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, int hp_profile_flag = 1; current_data = EG(current_execute_data); - func = hp_get_function_name(current_data->op_array TSRMLS_CC); + func = hp_get_function_name(¤t_data->func->op_array TSRMLS_CC); if (func) { BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag); @@ -1716,7 +1716,10 @@ 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 +#if ZEND_EXTENSION_API_NO >= 320140815 + + +#elif ZEND_EXTENSION_API_NO >= 220121212 /* PHP 5.5. This is just inlining a copy of execute_internal(). */ if (fci != NULL) { @@ -2006,18 +2009,20 @@ static char **hp_strings_in_zval(zval *values) { for (zend_hash_internal_pointer_reset(ht); zend_hash_has_more_elements(ht) == SUCCESS; zend_hash_move_forward(ht)) { - char *str; - uint len; + //char *str; + //uint len; + zend_string *key; + ulong idx; int type; zval **data; - - type = zend_hash_get_current_key_ex(ht, &str, &len, &idx, 0, NULL); + + type = zend_hash_get_current_key_ex(ht, &key, &idx, NULL); /* Get the names stored in a standard array */ if(type == HASH_KEY_IS_LONG) { - if ((zend_hash_get_current_data(ht, (void**)&data) == SUCCESS) && + if ((data = zend_hash_get_current_data(ht) != NULL) && Z_TYPE_PP(data) == IS_STRING && - strcmp(Z_STRVAL_PP(data), ROOT_SYMBOL)) { /* do not ignore "main" */ + strcmp(ZSTR_VAL((*data)->value.str), ROOT_SYMBOL)) { /* do not ignore "main" */ result[ix] = estrdup(Z_STRVAL_PP(data)); ix++; } From 8171946adddd36c7072d7c76df9981ce235864b6 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 20 Aug 2015 20:00:36 +0800 Subject: [PATCH 18/45] proxy zend_execute_internal in RINIT --- extension/xhprof.c | 121 ++++++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 39 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 00b45d81..c9ac5600 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -28,7 +28,9 @@ #include "php_ini.h" #include "ext/standard/info.h" #include "php_xhprof.h" -#include "zend_extensions.h" + +#include "zend_compile.h" + #include #include #include @@ -119,6 +121,19 @@ typedef unsigned char uint8; #endif +#if PHP_VERSION_ID < 50500 +#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) + +ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, + int ret TSRMLS_DC); +#else +#define EX_T(offset) (*EX_TMP_VAR(execute_data, offset)) + +ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, + struct _zend_fcall_info *fci, int ret TSRMLS_DC); +#endif + +typedef int (*opcode_handler_t) (zend_execute_data *execute_data); /** * ***************************** * GLOBAL DATATYPES AND TYPEDEFS @@ -233,6 +248,8 @@ typedef struct hp_global_t { /* XHProf global state */ static hp_global_t hp_globals; +int xhprof_icall_handler(ZEND_OPCODE_HANDLER_ARGS); + #if PHP_VERSION_ID < 50500 /* Pointer to the original execute function */ static ZEND_DLEXPORT void (*_zend_execute) (zend_op_array *ops TSRMLS_DC); @@ -480,6 +497,10 @@ PHP_MINIT_FUNCTION(xhprof) { /* To make it random number generator repeatable to ease testing. */ srand(0); #endif + zend_set_user_opcode_handler(ZEND_DO_ICALL, xhprof_icall_handler); + + zend_execute_internal = hp_execute_internal; + _zend_execute_internal = zend_execute_internal; return SUCCESS; } @@ -664,7 +685,8 @@ void hp_init_profiler_state(int level TSRMLS_DC) { /* Init stats_count */ if (hp_globals.stats_count) { zval_dtor(hp_globals.stats_count); - FREE_ZVAL(hp_globals.stats_count); + efree(hp_globals.stats_count); +// FREE_ZVAL(hp_globals.stats_count); } hp_globals.stats_count = (zval *)emalloc(sizeof(zval)); @@ -700,7 +722,8 @@ void hp_clean_profiler_state(TSRMLS_D) { /* Clear globals */ if (hp_globals.stats_count) { zval_dtor(hp_globals.stats_count); - FREE_ZVAL(hp_globals.stats_count); + efree(hp_globals.stats_count); + //FREE_ZVAL(hp_globals.stats_count); hp_globals.stats_count = NULL; } hp_globals.entries = NULL; @@ -776,11 +799,13 @@ void hp_clean_profiler_state(TSRMLS_D) { * @author veeve */ size_t hp_get_entry_name(hp_entry_t *entry, - char *result_buf, - size_t result_len) { + /*char *result_buf, + size_t result_len*/ + zend_string *result + ) { /* Validate result_len */ - if (result_len <= 1) { + if (result->len <= 1) { /* Insufficient result_bug. Bail! */ return 0; } @@ -788,20 +813,21 @@ size_t hp_get_entry_name(hp_entry_t *entry, /* Add '@recurse_level' if required */ /* NOTE: Dont use snprintf's return val as it is compiler dependent */ if (entry->rlvl_hprof) { - snprintf(result_buf, result_len, + snprintf(result->val, result->len, "%s@%d", entry->name_hprof, entry->rlvl_hprof); } else { - snprintf(result_buf, result_len, + snprintf(result->val, result->len, "%s", entry->name_hprof); } /* Force null-termination at MAX */ - result_buf[result_len - 1] = 0; - - return strlen(result_buf); +// result_buf[result_len - 1] = 0; + result->val[result->len - 1] = 0; + return result->len; + //return strlen(result_buf); } /** @@ -848,36 +874,38 @@ static inline int hp_ignore_entry(uint8 hash_code, char *curr_func) { */ size_t hp_get_function_stack(hp_entry_t *entry, int level, - char *result_buf, - size_t result_len) { + //char *result_buf, + //size_t result_len + zend_string *result + ) { size_t len = 0; /* End recursion if we dont need deeper levels or we dont have any deeper * levels */ if (!entry->prev_hprof || (level <= 1)) { - return hp_get_entry_name(entry, result_buf, result_len); + return hp_get_entry_name(entry, result); } /* Take care of all ancestors first */ len = hp_get_function_stack(entry->prev_hprof, level - 1, - result_buf, - result_len); + result + ); /* Append the delimiter */ # define HP_STACK_DELIM "==>" # define HP_STACK_DELIM_LEN (sizeof(HP_STACK_DELIM) - 1) - if (result_len < (len + HP_STACK_DELIM_LEN)) { + if (result->len < (len + HP_STACK_DELIM_LEN)) { /* Insufficient result_buf. Bail out! */ return len; } /* Add delimiter only if entry had ancestors */ if (len) { - strncat(result_buf + len, + strncat(result->val + len, HP_STACK_DELIM, - result_len - len); + result->len - len); len += HP_STACK_DELIM_LEN; } @@ -885,9 +913,9 @@ size_t hp_get_function_stack(hp_entry_t *entry, # undef HP_STACK_DELIM /* Append the current function name */ - return len + hp_get_entry_name(entry, - result_buf + len, - result_len - len); + //return len + hp_get_entry_name(entry, + // result->val + len, + // result->len - len); } /** @@ -976,7 +1004,7 @@ static char *hp_get_function_name(zend_op_array *ops TSRMLS_DC) { #elif ZEND_EXTENSION_API_NO >= 220100525 curr_op = data->opline->extended_value; #else - curr_op = data->opline->op2.u.constant.value.lval; + //curr_op = data->opline->op2.u.constant.value.lval; #endif switch (curr_op) { @@ -1085,14 +1113,14 @@ static void hp_fast_free_hprof_entry(hp_entry_t *p) { */ void hp_inc_count(zval *counts, zend_string *name, long count TSRMLS_DC) { HashTable *ht; - void *data; + zval *data; if (!counts) return; ht = HASH_OF(counts); if (!ht) return; - if (zend_hash_find(ht, name) == SUCCESS) { - ZVAL_LONG(*(zval**)data, Z_LVAL_PP((zval**)data) + count); + if ((data = zend_hash_find(ht, name)) != NULL) { + ZVAL_LONG(data, Z_LVAL_P(data) + count); } else { add_assoc_long(counts, name->val, count); } @@ -1104,9 +1132,9 @@ void hp_inc_count(zval *counts, zend_string *name, long count TSRMLS_DC) { * * @author kannan, veeve */ -zval * hp_hash_lookup(char *symbol TSRMLS_DC) { +zval * hp_hash_lookup(zend_string *symbol TSRMLS_DC) { HashTable *ht; - void *data; + zval *data; zval *counts = (zval *) 0; /* Bail if something is goofy */ @@ -1115,15 +1143,17 @@ zval * hp_hash_lookup(char *symbol TSRMLS_DC) { } /* Lookup our hash table */ - if (zend_hash_find(ht, zend_string_init(symbol, strlen(symbol) + 1, 0)) == SUCCESS) { + if ((data = zend_hash_find(ht, symbol)) != NULL) { /* Symbol already exists */ counts = *(zval **) data; } else { /* Add symbol to hash table */ - MAKE_STD_ZVAL(counts); + // MAKE_STD_ZVAL(counts); + counts = (zval *)emalloc(sizeof(zval)); array_init(counts); - add_assoc_zval(hp_globals.stats_count, symbol, counts); + add_assoc_zval(hp_globals.stats_count, symbol->val, counts); + //zend_hash_update(Z_ARRVAL_P(hp_globals.stats_count), symbol, counts); } return counts; @@ -1162,7 +1192,9 @@ void hp_trunc_time(struct timeval *tv, */ void hp_sample_stack(hp_entry_t **entries TSRMLS_DC) { char key[SCRATCH_BUF_LEN]; - char symbol[SCRATCH_BUF_LEN * 1000]; + //char symbol[SCRATCH_BUF_LEN * 1000]; + zend_string *symbol; + symbol = zend_string_alloc(SCRATCH_BUF_LEN * 1000, 0); /* Build key */ snprintf(key, sizeof(key), @@ -1173,8 +1205,8 @@ void hp_sample_stack(hp_entry_t **entries TSRMLS_DC) { /* Init stats in the global stats_count hashtable */ hp_get_function_stack(*entries, INT_MAX, - symbol, - sizeof(symbol)); + symbol + ); add_assoc_string(hp_globals.stats_count, key, @@ -1562,7 +1594,7 @@ void hp_mode_sampled_beginfn_cb(hp_entry_t **entries, * @author kannan */ zval * hp_mode_shared_endfn_cb(hp_entry_t *top, - char *symbol TSRMLS_DC) { + zend_string *symbol TSRMLS_DC) { zval *counts; uint64 tsc_end; @@ -1591,12 +1623,14 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { hp_entry_t *top = (*entries); zval *counts; struct rusage ru_end; - char symbol[SCRATCH_BUF_LEN]; +// char symbol[SCRATCH_BUF_LEN]; + zend_string *symbol; long int mu_end; long int pmu_end; /* Get the stat array */ - hp_get_function_stack(top, 2, symbol, sizeof(symbol)); + symbol = zend_string_alloc(SCRATCH_BUF_LEN, 0); + hp_get_function_stack(top, 2, symbol); if (!(counts = hp_mode_shared_endfn_cb(top, symbol TSRMLS_CC))) { return; @@ -1751,12 +1785,12 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, EX(object), ret TSRMLS_CC); #else zend_op *opline = EX(opline); - ((zend_internal_function *) EX(function_state).function)->handler( + /*((zend_internal_function *) EX(function_state).function)->handler( opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(function_state).function->common.return_reference ? &EX_T(opline->result.u.var).var.ptr:NULL, - EX(object), ret TSRMLS_CC); + EX(object), ret TSRMLS_CC);*/ #endif } else { /* call the old override */ @@ -1856,6 +1890,7 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { zend_compile_string = hp_compile_string; /* Replace zend_execute with our proxy */ + #if PHP_VERSION_ID < 50500 _zend_execute = zend_execute; zend_execute = hp_execute; @@ -2056,3 +2091,11 @@ static inline void hp_array_del(char **name_array) { efree(name_array); } } +inline int xhprof_icall_handler(zend_execute_data *execute_data) { + zend_op *opline = execute_data->opline; + + php_printf("before\n"); +// zend_opcode_handlers[opline->opcode + 1](execute_data); + php_printf("after\n"); + return ZEND_USER_OPCODE_DISPATCH; +} From e9b97bca9c7c7a61cba4c3ce7db6eed4c50054fe Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 21 Aug 2015 18:56:59 +0800 Subject: [PATCH 19/45] ok now could run simple program, user funciton supported not finished --- extension/xhprof.c | 186 +++++++++++++++------------------------------ 1 file changed, 63 insertions(+), 123 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index c9ac5600..2d93f153 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -121,19 +121,10 @@ typedef unsigned char uint8; #endif -#if PHP_VERSION_ID < 50500 -#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) -ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, - int ret TSRMLS_DC); -#else -#define EX_T(offset) (*EX_TMP_VAR(execute_data, offset)) -ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, - struct _zend_fcall_info *fci, int ret TSRMLS_DC); -#endif -typedef int (*opcode_handler_t) (zend_execute_data *execute_data); + /** * ***************************** * GLOBAL DATATYPES AND TYPEDEFS @@ -248,23 +239,6 @@ typedef struct hp_global_t { /* XHProf global state */ static hp_global_t hp_globals; -int xhprof_icall_handler(ZEND_OPCODE_HANDLER_ARGS); - -#if PHP_VERSION_ID < 50500 -/* Pointer to the original execute function */ -static ZEND_DLEXPORT void (*_zend_execute) (zend_op_array *ops TSRMLS_DC); - -/* Pointer to the origianl execute_internal function */ -static ZEND_DLEXPORT void (*_zend_execute_internal) (zend_execute_data *data, - int ret TSRMLS_DC); -#else -/* Pointer to the original execute function */ -static void (*_zend_execute_ex) (zend_execute_data *execute_data TSRMLS_DC); - -/* Pointer to the origianl execute_internal function */ -static void (*_zend_execute_internal) (zend_execute_data *data, - struct _zend_fcall_info *fci, int ret TSRMLS_DC); -#endif /* Pointer to the original compile function */ static zend_op_array * (*_zend_compile_file) (zend_file_handle *file_handle, @@ -278,6 +252,31 @@ static zend_op_array * (*_zend_compile_string) (zval *source_string, char *filen #define INDEX_2_BIT(index) (1 << (index & 0x7)); +/** + * *************************** + * XHPROF DUMMY CALLBACKS + * *************************** + */ +void hp_mode_dummy_init_cb(TSRMLS_D); + +void hp_mode_dummy_exit_cb(TSRMLS_D); + +void hp_mode_dummy_beginfn_cb(hp_entry_t **entries, + hp_entry_t *current TSRMLS_DC); + +void hp_mode_dummy_endfn_cb(hp_entry_t **entries TSRMLS_DC); + +/* Pointer to the original execute function */ +static void (*_zend_execute_ex) (zend_execute_data *execute_data TSRMLS_DC); + +/* Pointer to the origianl execute_internal function */ +static void (*_zend_execute_internal) (zend_execute_data *data, zval *ret TSRMLS_DC); +#define EX_T(offset) (*EX_TMP_VAR(execute_data, offset)) + +ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval* ret TSRMLS_DC); + +ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC); + /** * **************************** * STATIC FUNCTION DECLARATIONS @@ -487,6 +486,13 @@ PHP_MINIT_FUNCTION(xhprof) { /* no free hp_entry_t structures to start with */ hp_globals.entry_free_list = NULL; + /* Initialize with the dummy mode first Having these dummy callbacks saves + * us from checking if any of the callbacks are NULL everywhere. */ + hp_globals.mode_cb.init_cb = hp_mode_dummy_init_cb; + hp_globals.mode_cb.exit_cb = hp_mode_dummy_exit_cb; + hp_globals.mode_cb.begin_fn_cb = hp_mode_dummy_beginfn_cb; + hp_globals.mode_cb.end_fn_cb = hp_mode_dummy_endfn_cb; + for (i = 0; i < 256; i++) { hp_globals.func_hash_counters[i] = 0; } @@ -497,10 +503,12 @@ PHP_MINIT_FUNCTION(xhprof) { /* To make it random number generator repeatable to ease testing. */ srand(0); #endif - zend_set_user_opcode_handler(ZEND_DO_ICALL, xhprof_icall_handler); - zend_execute_internal = hp_execute_internal; _zend_execute_internal = zend_execute_internal; + zend_execute_internal = hp_execute_internal; + + _zend_execute_ex = zend_execute_ex; + zend_execute_ex = hp_execute_ex; return SUCCESS; } @@ -1682,33 +1690,22 @@ void hp_mode_sampled_endfn_cb(hp_entry_t **entries TSRMLS_DC) { * new execute function. We can do whatever profiling we need to * before and after calling the actual zend_execute(). * - * @author hzhao, kannan + * @author hzhao, kannan, Jason */ -#if PHP_VERSION_ID < 50500 -ZEND_DLEXPORT void hp_execute (zend_op_array *ops TSRMLS_DC) { -#else ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { zend_op_array *ops = &execute_data->func->op_array; -#endif - char *func = NULL; + zend_string *func = NULL; int hp_profile_flag = 1; - func = hp_get_function_name(ops TSRMLS_CC); + //func = hp_get_function_name(ops TSRMLS_CC); + func = execute_data->func->internal_function.function_name; if (!func) { -#if PHP_VERSION_ID < 50500 - _zend_execute(ops TSRMLS_CC); -#else _zend_execute_ex(execute_data TSRMLS_CC); -#endif return; } BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag); -#if PHP_VERSION_ID < 50500 - _zend_execute(ops TSRMLS_CC); -#else _zend_execute_ex(execute_data TSRMLS_CC); -#endif if (hp_globals.entries) { END_PROFILING(&hp_globals.entries, hp_profile_flag); } @@ -1722,20 +1719,13 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { * Very similar to hp_execute. Proxy for zend_execute_internal(). * Applies to zend builtin functions. * - * @author hzhao, kannan + * @author hzhao, kannan, Jason */ -#if PHP_VERSION_ID < 50500 -#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) -ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, - int ret TSRMLS_DC) { -#else #define EX_T(offset) (*EX_TMP_VAR(execute_data, offset)) -ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, - struct _zend_fcall_info *fci, int ret TSRMLS_DC) { -#endif +ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *ret TSRMLS_DC) { zend_execute_data *current_data; char *func = NULL; int hp_profile_flag = 1; @@ -1750,55 +1740,12 @@ 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 >= 320140815 - - -#elif 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); - temp_variable *retvar = &EX_T(opline->result.var); - ((zend_internal_function *) EX(function_state).function)->handler( - opline->extended_value, - retvar->var.ptr, - (EX(function_state).function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? - &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, - EX(function_state).function->common.return_reference ? - &EX_T(opline->result.u.var).var.ptr:NULL, - EX(object), ret TSRMLS_CC);*/ -#endif + execute_data ->func ->internal_function.handler(execute_data, ret); + } else { /* call the old override */ -#if PHP_VERSION_ID < 50500 _zend_execute_internal(execute_data, ret TSRMLS_CC); -#else - _zend_execute_internal(execute_data, fci, ret TSRMLS_CC); -#endif } if (func) { @@ -1880,6 +1827,23 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { hp_globals.enabled = 1; hp_globals.xhprof_flags = (uint32)xhprof_flags; + hp_init_profiler_state(level TSRMLS_CC); + + /* Register the appropriate callback functions Override just a subset of + * all the callbacks is OK. */ + switch(level) { + case XHPROF_MODE_HIERARCHICAL: + hp_globals.mode_cb.begin_fn_cb = hp_mode_hier_beginfn_cb; + hp_globals.mode_cb.end_fn_cb = hp_mode_hier_endfn_cb; + break; + case XHPROF_MODE_SAMPLED: + hp_globals.mode_cb.init_cb = hp_mode_sampled_init_cb; + hp_globals.mode_cb.begin_fn_cb = hp_mode_sampled_beginfn_cb; + hp_globals.mode_cb.end_fn_cb = hp_mode_sampled_endfn_cb; + break; + } + /* return here or recu*/ + return; /* Replace zend_compile with our proxy */ _zend_compile_file = zend_compile_file; @@ -1891,13 +1855,8 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { /* Replace zend_execute with our proxy */ -#if PHP_VERSION_ID < 50500 - _zend_execute = zend_execute; - zend_execute = hp_execute; -#else _zend_execute_ex = zend_execute_ex; zend_execute_ex = hp_execute_ex; -#endif /* Replace zend_execute_internal with our proxy */ _zend_execute_internal = zend_execute_internal; @@ -1908,32 +1867,13 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { zend_execute_internal = hp_execute_internal; } - /* Initialize with the dummy mode first Having these dummy callbacks saves - * us from checking if any of the callbacks are NULL everywhere. */ - hp_globals.mode_cb.init_cb = hp_mode_dummy_init_cb; - hp_globals.mode_cb.exit_cb = hp_mode_dummy_exit_cb; - hp_globals.mode_cb.begin_fn_cb = hp_mode_dummy_beginfn_cb; - hp_globals.mode_cb.end_fn_cb = hp_mode_dummy_endfn_cb; - /* Register the appropriate callback functions Override just a subset of - * all the callbacks is OK. */ - switch(level) { - case XHPROF_MODE_HIERARCHICAL: - hp_globals.mode_cb.begin_fn_cb = hp_mode_hier_beginfn_cb; - hp_globals.mode_cb.end_fn_cb = hp_mode_hier_endfn_cb; - break; - case XHPROF_MODE_SAMPLED: - hp_globals.mode_cb.init_cb = hp_mode_sampled_init_cb; - hp_globals.mode_cb.begin_fn_cb = hp_mode_sampled_beginfn_cb; - hp_globals.mode_cb.end_fn_cb = hp_mode_sampled_endfn_cb; - break; - } /* one time initializations */ hp_init_profiler_state(level TSRMLS_CC); /* start profiling from fictitious main() */ - BEGIN_PROFILING(&hp_globals.entries, ROOT_SYMBOL, hp_profile_flag); + //BEGIN_PROFILING(&hp_globals.entries, ROOT_SYMBOL, hp_profile_flag); } } From 6c473e39fa93fb7f0acc3fae73f626e5c66dff1a Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 24 Aug 2015 19:16:26 +0800 Subject: [PATCH 20/45] no seg bug mem still leaks. --- extension/xhprof.c | 221 ++++++++++++++++++++++----------------------- 1 file changed, 109 insertions(+), 112 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 2d93f153..2087d6e2 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -139,7 +139,7 @@ typedef unsigned char uint8; * profile operation, recursion depth, and the name of the function being * profiled. */ typedef struct hp_entry_t { - char *name_hprof; /* function name */ + zend_string *name_hprof; /* function name */ int rlvl_hprof; /* recursion level for function */ uint64 tsc_start; /* start value for TSC counter */ long int mu_start_hprof; /* memory usage */ @@ -729,7 +729,7 @@ void hp_clean_profiler_state(TSRMLS_D) { /* Clear globals */ if (hp_globals.stats_count) { - zval_dtor(hp_globals.stats_count); + //zval_dtor(hp_globals.stats_count); efree(hp_globals.stats_count); //FREE_ZVAL(hp_globals.stats_count); hp_globals.stats_count = NULL; @@ -754,8 +754,8 @@ void hp_clean_profiler_state(TSRMLS_D) { #define BEGIN_PROFILING(entries, symbol, profile_curr) \ do { \ /* Use a hash code to filter most of the string comparisons. */ \ - uint8 hash_code = hp_inline_hash(symbol); \ - profile_curr = !hp_ignore_entry(hash_code, symbol); \ + uint8 hash_code = hp_inline_hash(symbol->val); \ + profile_curr = !hp_ignore_entry(hash_code, symbol->val); \ if (profile_curr) { \ hp_entry_t *cur_entry = hp_fast_alloc_hprof_entry(); \ (cur_entry)->hash_code = hash_code; \ @@ -823,19 +823,18 @@ size_t hp_get_entry_name(hp_entry_t *entry, if (entry->rlvl_hprof) { snprintf(result->val, result->len, "%s@%d", - entry->name_hprof, entry->rlvl_hprof); + entry->name_hprof->val, entry->rlvl_hprof); } else { - snprintf(result->val, result->len, + snprintf(result->val + strlen(result->val), result->len, "%s", - entry->name_hprof); + entry->name_hprof->val); } /* Force null-termination at MAX */ // result_buf[result_len - 1] = 0; result->val[result->len - 1] = 0; - return result->len; - //return strlen(result_buf); + return strlen(result->val); } /** @@ -882,8 +881,6 @@ static inline int hp_ignore_entry(uint8 hash_code, char *curr_func) { */ size_t hp_get_function_stack(hp_entry_t *entry, int level, - //char *result_buf, - //size_t result_len zend_string *result ) { size_t len = 0; @@ -921,9 +918,7 @@ size_t hp_get_function_stack(hp_entry_t *entry, # undef HP_STACK_DELIM /* Append the current function name */ - //return len + hp_get_entry_name(entry, - // result->val + len, - // result->len - len); + return len + hp_get_entry_name(entry, result); } /** @@ -1199,27 +1194,29 @@ void hp_trunc_time(struct timeval *tv, * @author veeve */ void hp_sample_stack(hp_entry_t **entries TSRMLS_DC) { - char key[SCRATCH_BUF_LEN]; - //char symbol[SCRATCH_BUF_LEN * 1000]; - zend_string *symbol; - symbol = zend_string_alloc(SCRATCH_BUF_LEN * 1000, 0); - - /* Build key */ - snprintf(key, sizeof(key), - "%d.%06d", - hp_globals.last_sample_time.tv_sec, - hp_globals.last_sample_time.tv_usec); - - /* Init stats in the global stats_count hashtable */ - hp_get_function_stack(*entries, - INT_MAX, - symbol - ); - - add_assoc_string(hp_globals.stats_count, - key, - symbol); - return; + +// //char symbol[SCRATCH_BUF_LEN * 1000]; +// zend_string *symbol; +// zend_string *key; +// symbol = zend_string_alloc(SCRATCH_BUF_LEN * 1000, 0); +// key = zend_string_alloc(SCRATCH_BUF_LEN, 0); +// +// /* Build key */ +// snprintf(key->val, key->len, +// "%d.%06d", +// hp_globals.last_sample_time.tv_sec, +// hp_globals.last_sample_time.tv_usec); +// +// /* Init stats in the global stats_count hashtable */ +// hp_get_function_stack(*entries, +// INT_MAX, +// symbol +// ); +// +// add_assoc_string(hp_globals.stats_count, +// key->val, +// symbol->val); +// return; } /** @@ -1486,7 +1483,7 @@ void hp_mode_common_beginfn(hp_entry_t **entries, if (hp_globals.func_hash_counters[current->hash_code] > 0) { /* Find this symbols recurse level */ for(p = (*entries); p; p = p->prev_hprof) { - if (!strcmp(current->name_hprof, p->name_hprof)) { + if (!strcmp(current->name_hprof->val, p->name_hprof->val)) { recurse_level = (p->rlvl_hprof) + 1; break; } @@ -1638,6 +1635,7 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { /* Get the stat array */ symbol = zend_string_alloc(SCRATCH_BUF_LEN, 0); + ZSTR_VAL(symbol)[0] = '\000'; hp_get_function_stack(top, 2, symbol); if (!(counts = hp_mode_shared_endfn_cb(top, symbol TSRMLS_CC))) { @@ -1666,6 +1664,7 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { hp_inc_count(counts, zend_string_init("mu", sizeof("mu") - 1, 0), mu_end - top->mu_start_hprof TSRMLS_CC); hp_inc_count(counts, zend_string_init("pmu", sizeof("pmu") - 1, 0), pmu_end - top->pmu_start_hprof TSRMLS_CC); } + zend_string_free(symbol); } /** @@ -1709,7 +1708,7 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { if (hp_globals.entries) { END_PROFILING(&hp_globals.entries, hp_profile_flag); } - efree(func); + //zend_string_free(func); } #undef EX @@ -1727,20 +1726,21 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *ret TSRMLS_DC) { zend_execute_data *current_data; - char *func = NULL; + zend_string *func = NULL; int hp_profile_flag = 1; current_data = EG(current_execute_data); - func = hp_get_function_name(¤t_data->func->op_array TSRMLS_CC); + //func = hp_get_function_name(¤t_data->func->op_array TSRMLS_CC); + func = current_data->func->op_array.function_name ; - if (func) { + if (func && strcmp("xhprof_enable", func->val) != 0) { BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag); } if (!_zend_execute_internal) { /* no old override to begin with. so invoke the builtin's implementation */ - zend_op *opline = EX(opline); + //zend_op *opline = EX(opline); execute_data ->func ->internal_function.handler(execute_data, ret); } else { @@ -1748,11 +1748,11 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re _zend_execute_internal(execute_data, ret TSRMLS_CC); } - if (func) { + if (func && strcmp("xhprof_enable", func->val) != 0) { if (hp_globals.entries) { END_PROFILING(&hp_globals.entries, hp_profile_flag); } - efree(func); + //zend_string_free(func); } } @@ -1765,7 +1765,7 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) { - const char *filename; + /*const char *filename; char *func; int len; zend_op_array *ret; @@ -1783,7 +1783,7 @@ ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, } efree(func); - return ret; + return ret;*/ } /** @@ -1791,7 +1791,7 @@ ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, */ ZEND_DLEXPORT zend_op_array* hp_compile_string(zval *source_string, char *filename TSRMLS_DC) { - char *func; + /*char *func; int len; zend_op_array *ret; int hp_profile_flag = 1; @@ -1807,7 +1807,7 @@ ZEND_DLEXPORT zend_op_array* hp_compile_string(zval *source_string, char *filena } efree(func); - return ret; + return ret;*/ } /** @@ -1842,6 +1842,7 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { hp_globals.mode_cb.end_fn_cb = hp_mode_sampled_endfn_cb; break; } + BEGIN_PROFILING(&hp_globals.entries, zend_string_init(ROOT_SYMBOL, sizeof(ROOT_SYMBOL) - 1, 0), hp_profile_flag); /* return here or recu*/ return; @@ -1908,14 +1909,10 @@ static void hp_stop(TSRMLS_D) { } /* Remove proxies, restore the originals */ -#if PHP_VERSION_ID < 50500 - zend_execute = _zend_execute; -#else zend_execute_ex = _zend_execute_ex; -#endif zend_execute_internal = _zend_execute_internal; - zend_compile_file = _zend_compile_file; - zend_compile_string = _zend_compile_string; + //zend_compile_file = _zend_compile_file; + //zend_compile_string = _zend_compile_string; /* Resore cpu affinity. */ restore_cpu_affinity(&hp_globals.prev_mask); @@ -1962,63 +1959,63 @@ static zval *hp_zval_at_key(char *key, * @author mpal **/ static char **hp_strings_in_zval(zval *values) { - char **result; - size_t count; - size_t ix = 0; - - if (!values) { - return NULL; - } - - if (Z_TYPE_P(values) == IS_ARRAY) { - HashTable *ht; - - ht = Z_ARRVAL_P(values); - count = zend_hash_num_elements(ht); - - if((result = - (char**)emalloc(sizeof(char*) * (count + 1))) == NULL) { - return result; - } - - for (zend_hash_internal_pointer_reset(ht); - zend_hash_has_more_elements(ht) == SUCCESS; - zend_hash_move_forward(ht)) { - //char *str; - //uint len; - zend_string *key; - - ulong idx; - int type; - zval **data; - - type = zend_hash_get_current_key_ex(ht, &key, &idx, NULL); - /* Get the names stored in a standard array */ - if(type == HASH_KEY_IS_LONG) { - if ((data = zend_hash_get_current_data(ht) != NULL) && - Z_TYPE_PP(data) == IS_STRING && - strcmp(ZSTR_VAL((*data)->value.str), ROOT_SYMBOL)) { /* do not ignore "main" */ - result[ix] = estrdup(Z_STRVAL_PP(data)); - ix++; - } - } - } - } else if(Z_TYPE_P(values) == IS_STRING) { - if((result = (char**)emalloc(sizeof(char*) * 2)) == NULL) { - return result; - } - result[0] = estrdup(Z_STRVAL_P(values)); - ix = 1; - } else { - result = NULL; - } - - /* NULL terminate the array */ - if (result != NULL) { - result[ix] = NULL; - } - - return result; +// char **result; +// size_t count; +// size_t ix = 0; +// +// if (!values) { +// return NULL; +// } +// +// if (Z_TYPE_P(values) == IS_ARRAY) { +// HashTable *ht; +// +// ht = Z_ARRVAL_P(values); +// count = zend_hash_num_elements(ht); +// +// if((result = +// (char**)emalloc(sizeof(char*) * (count + 1))) == NULL) { +// return result; +// } +// +// for (zend_hash_internal_pointer_reset(ht); +// zend_hash_has_more_elements(ht) == SUCCESS; +// zend_hash_move_forward(ht)) { +// //char *str; +// //uint len; +// zend_string *key; +// +// ulong idx; +// int type; +// zval **data; +// +// type = zend_hash_get_current_key_ex(ht, &key, &idx, NULL); +// /* Get the names stored in a standard array */ +// if(type == HASH_KEY_IS_LONG) { +// if ((data = zend_hash_get_current_data(ht) != NULL) && +// Z_TYPE_PP(data) == IS_STRING && +// strcmp(ZSTR_VAL((*data)->value.str), ROOT_SYMBOL)) { /* do not ignore "main" */ +// result[ix] = estrdup(Z_STRVAL_PP(data)); +// ix++; +// } +// } +// } +// } else if(Z_TYPE_P(values) == IS_STRING) { +// if((result = (char**)emalloc(sizeof(char*) * 2)) == NULL) { +// return result; +// } +// result[0] = estrdup(Z_STRVAL_P(values)); +// ix = 1; +// } else { +// result = NULL; +// } +// +// /* NULL terminate the array */ +// if (result != NULL) { +// result[ix] = NULL; +// } +// +// return result; } /* Free this memory at the end of profiling */ @@ -2031,11 +2028,11 @@ static inline void hp_array_del(char **name_array) { efree(name_array); } } -inline int xhprof_icall_handler(zend_execute_data *execute_data) { +/*inline int xhprof_icall_handler(zend_execute_data *execute_data) { zend_op *opline = execute_data->opline; php_printf("before\n"); // zend_opcode_handlers[opline->opcode + 1](execute_data); php_printf("after\n"); return ZEND_USER_OPCODE_DISPATCH; -} +}*/ From 07fdb4f823545c3f68dcd9d26001e526f3524ec6 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 28 Aug 2015 13:39:25 +0800 Subject: [PATCH 21/45] comment out unused code --- extension/xhprof.c | 98 ++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 2087d6e2..f2210494 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -625,19 +625,19 @@ 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; - - zresult = hp_zval_at_key("ignored_functions", args); - hp_globals.ignored_function_names = hp_strings_in_zval(zresult); - } else { - hp_globals.ignored_function_names = NULL; - } +// +// if (hp_globals.ignored_function_names) { +// hp_array_del(hp_globals.ignored_function_names); +// } +// +// if (args != NULL) { +// zval *zresult = NULL; +// +// zresult = hp_zval_at_key("ignored_functions", args); +// hp_globals.ignored_function_names = hp_strings_in_zval(zresult); +// } else { +// hp_globals.ignored_function_names = NULL; +// } } /** @@ -646,8 +646,8 @@ static void hp_get_ignored_functions_from_arg(zval *args) { * @author mpal */ static void hp_ignored_functions_filter_clear() { - memset(hp_globals.ignored_function_filter, 0, - XHPROF_IGNORED_FUNCTION_FILTER_SIZE); +// memset(hp_globals.ignored_function_filter, 0, +// XHPROF_IGNORED_FUNCTION_FILTER_SIZE); } /** @@ -730,6 +730,7 @@ void hp_clean_profiler_state(TSRMLS_D) { /* Clear globals */ if (hp_globals.stats_count) { //zval_dtor(hp_globals.stats_count); + zend_array_destroy(Z_ARRVAL_P(hp_globals.stats_count)); efree(hp_globals.stats_count); //FREE_ZVAL(hp_globals.stats_count); hp_globals.stats_count = NULL; @@ -739,7 +740,7 @@ void hp_clean_profiler_state(TSRMLS_D) { hp_globals.ever_enabled = 0; /* Delete the array storing ignored function names */ - hp_array_del(hp_globals.ignored_function_names); + //hp_array_del(hp_globals.ignored_function_names); hp_globals.ignored_function_names = NULL; } @@ -1125,6 +1126,10 @@ void hp_inc_count(zval *counts, zend_string *name, long count TSRMLS_DC) { if ((data = zend_hash_find(ht, name)) != NULL) { ZVAL_LONG(data, Z_LVAL_P(data) + count); } else { + + //ZVAL_LONG(data, count); + //zend_hash_update(ht, name, data); + add_assoc_long(counts, name->val, count); } } @@ -1138,7 +1143,7 @@ void hp_inc_count(zval *counts, zend_string *name, long count TSRMLS_DC) { zval * hp_hash_lookup(zend_string *symbol TSRMLS_DC) { HashTable *ht; zval *data; - zval *counts = (zval *) 0; + zval *counts; /* Bail if something is goofy */ if (!hp_globals.stats_count || !(ht = HASH_OF(hp_globals.stats_count))) { @@ -1155,10 +1160,15 @@ zval * hp_hash_lookup(zend_string *symbol TSRMLS_DC) { // MAKE_STD_ZVAL(counts); counts = (zval *)emalloc(sizeof(zval)); array_init(counts); + //zval_dtor(counts); add_assoc_zval(hp_globals.stats_count, symbol->val, counts); - //zend_hash_update(Z_ARRVAL_P(hp_globals.stats_count), symbol, counts); + /*if (Z_REFCOUNTED_P(counts)) { + Z_ADDREF_P(counts); + } + //zend_hash_add_new(Z_ARRVAL_P(hp_globals.stats_count), zend_string_copy(symbol), counts); + zend_hash_update(Z_ARRVAL_P(hp_globals.stats_count), zend_string_dup(symbol, 0), counts);*/ } - + return counts; } @@ -1628,7 +1638,6 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { hp_entry_t *top = (*entries); zval *counts; struct rusage ru_end; -// char symbol[SCRATCH_BUF_LEN]; zend_string *symbol; long int mu_end; long int pmu_end; @@ -1639,6 +1648,7 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { hp_get_function_stack(top, 2, symbol); if (!(counts = hp_mode_shared_endfn_cb(top, symbol TSRMLS_CC))) { + efree(symbol); return; } @@ -1664,6 +1674,8 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { hp_inc_count(counts, zend_string_init("mu", sizeof("mu") - 1, 0), mu_end - top->mu_start_hprof TSRMLS_CC); hp_inc_count(counts, zend_string_init("pmu", sizeof("pmu") - 1, 0), pmu_end - top->pmu_start_hprof TSRMLS_CC); } + + efree(counts); zend_string_free(symbol); } @@ -1935,22 +1947,22 @@ static void hp_stop(TSRMLS_D) { **/ static zval *hp_zval_at_key(char *key, zval *values) { - zval *result = NULL; - - if (Z_TYPE_P(values) == IS_ARRAY) { - HashTable *ht; - zval **value; - uint len = strlen(key) + 1; - - ht = Z_ARRVAL_P(values); - if (zend_hash_find(ht, zend_string_init(key, len, 0)) == SUCCESS) { - result = *value; - } - } else { - result = NULL; - } - - return result; +// zval *result = NULL; +// +// if (Z_TYPE_P(values) == IS_ARRAY) { +// HashTable *ht; +// zval **value; +// uint len = strlen(key) + 1; +// +// ht = Z_ARRVAL_P(values); +// if (zend_hash_find(ht, zend_string_init(key, len, 0)) == SUCCESS) { +// result = *value; +// } +// } else { +// result = NULL; +// } +// +// return result; } /** Convert the PHP array of strings to an emalloced array of strings. Note, @@ -2020,13 +2032,13 @@ static char **hp_strings_in_zval(zval *values) { /* Free this memory at the end of profiling */ static inline void hp_array_del(char **name_array) { - if (name_array != NULL) { - int i = 0; - for(; name_array[i] != NULL && i < XHPROF_MAX_IGNORED_FUNCTIONS; i++) { - efree(name_array[i]); - } - efree(name_array); - } +// if (name_array != NULL) { +// int i = 0; +// for(; name_array[i] != NULL && i < XHPROF_MAX_IGNORED_FUNCTIONS; i++) { +// efree(name_array[i]); +// } +// efree(name_array); +// } } /*inline int xhprof_icall_handler(zend_execute_data *execute_data) { zend_op *opline = execute_data->opline; From 8ddfbd05b58d30bd064af0f3931b079ca482a966 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 28 Aug 2015 13:42:14 +0800 Subject: [PATCH 22/45] fix mem leaks --- extension/xhprof.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index f2210494..d14913ee 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -1622,9 +1622,9 @@ zval * hp_mode_shared_endfn_cb(hp_entry_t *top, } /* Bump stats in the counts hashtable */ - hp_inc_count(counts, zend_string_init("ct", sizeof("ct") - 1, 0), 1 TSRMLS_CC); + hp_inc_count(counts, zend_string_init("ct", sizeof("ct") - 1, 1), 1 TSRMLS_CC); - hp_inc_count(counts, zend_string_init("wt", sizeof("wt") - 1, 0), get_us_from_tsc(tsc_end - top->tsc_start, + hp_inc_count(counts, zend_string_init("wt", sizeof("wt") - 1, 1), get_us_from_tsc(tsc_end - top->tsc_start, hp_globals.cpu_frequencies[hp_globals.cur_cpu_id]) TSRMLS_CC); return counts; } @@ -1657,7 +1657,7 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { getrusage(RUSAGE_SELF, &ru_end); /* Bump CPU stats in the counts hashtable */ - hp_inc_count(counts, zend_string_init("cpu", sizeof("cpu") - 1, 0), (get_us_interval(&(top->ru_start_hprof.ru_utime), + hp_inc_count(counts, zend_string_init("cpu", sizeof("cpu") - 1, 1), (get_us_interval(&(top->ru_start_hprof.ru_utime), &(ru_end.ru_utime)) + get_us_interval(&(top->ru_start_hprof.ru_stime), &(ru_end.ru_stime))) @@ -1671,8 +1671,8 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { /* Bump Memory stats in the counts hashtable */ - hp_inc_count(counts, zend_string_init("mu", sizeof("mu") - 1, 0), mu_end - top->mu_start_hprof TSRMLS_CC); - hp_inc_count(counts, zend_string_init("pmu", sizeof("pmu") - 1, 0), pmu_end - top->pmu_start_hprof TSRMLS_CC); + hp_inc_count(counts, zend_string_init("mu", sizeof("mu") - 1, 1), mu_end - top->mu_start_hprof TSRMLS_CC); + hp_inc_count(counts, zend_string_init("pmu", sizeof("pmu") - 1, 1), pmu_end - top->pmu_start_hprof TSRMLS_CC); } efree(counts); @@ -1854,7 +1854,7 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { hp_globals.mode_cb.end_fn_cb = hp_mode_sampled_endfn_cb; break; } - BEGIN_PROFILING(&hp_globals.entries, zend_string_init(ROOT_SYMBOL, sizeof(ROOT_SYMBOL) - 1, 0), hp_profile_flag); + BEGIN_PROFILING(&hp_globals.entries, zend_string_init(ROOT_SYMBOL, sizeof(ROOT_SYMBOL) - 1, 1), hp_profile_flag); /* return here or recu*/ return; From 231ec6f186e091d0a86a01a26749dd69f8bc44b3 Mon Sep 17 00:00:00 2001 From: sunan <327369214@qq.com> Date: Fri, 4 Sep 2015 00:04:50 +0800 Subject: [PATCH 23/45] add url --- examples/sample.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/sample.php b/examples/sample.php index 44b9fdb8..21b8b0d2 100644 --- a/examples/sample.php +++ b/examples/sample.php @@ -37,8 +37,9 @@ function foo() { // save the run under a namespace "xhprof_foo" $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo"); + echo "---------------\n". "Assuming you have set up the http based UI for \n". "XHProf at some address, you can view run at \n". - "http:///index.php?run=$run_id&source=xhprof_foo\n". + "click here\n". "---------------\n"; From 2053ce44cef5f8273cd4e974e395e04a406c46f0 Mon Sep 17 00:00:00 2001 From: sunan <327369214@qq.com> Date: Fri, 4 Sep 2015 02:01:37 +0800 Subject: [PATCH 24/45] function well but mem leaks a little --- examples/sample.php | 5 ++++- extension/xhprof.c | 21 ++++++++------------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/examples/sample.php b/examples/sample.php index 21b8b0d2..1be370d3 100644 --- a/examples/sample.php +++ b/examples/sample.php @@ -17,7 +17,10 @@ function foo() { xhprof_enable(); // run program -foo(); +for ($i = 0; $i < 1000; $i++) { + + foo(); +} // stop profiler $xhprof_data = xhprof_disable(); diff --git a/extension/xhprof.c b/extension/xhprof.c index d14913ee..53466e83 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -729,11 +729,11 @@ void hp_clean_profiler_state(TSRMLS_D) { /* Clear globals */ if (hp_globals.stats_count) { - //zval_dtor(hp_globals.stats_count); - zend_array_destroy(Z_ARRVAL_P(hp_globals.stats_count)); - efree(hp_globals.stats_count); + Z_DELREF_P(hp_globals.stats_count); + //zend_array_destroy(Z_ARRVAL_P(hp_globals.stats_count)); + //efree(hp_globals.stats_count); //FREE_ZVAL(hp_globals.stats_count); - hp_globals.stats_count = NULL; + //hp_globals.stats_count = NULL; } hp_globals.entries = NULL; hp_globals.profiler_level = 1; @@ -1151,22 +1151,17 @@ zval * hp_hash_lookup(zend_string *symbol TSRMLS_DC) { } /* Lookup our hash table */ - if ((data = zend_hash_find(ht, symbol)) != NULL) { + //zend_hash_str_find + if ((data = zend_hash_str_find(ht, symbol->val, strlen(symbol->val))) != NULL) { /* Symbol already exists */ - counts = *(zval **) data; + counts = data; } else { /* Add symbol to hash table */ // MAKE_STD_ZVAL(counts); counts = (zval *)emalloc(sizeof(zval)); array_init(counts); - //zval_dtor(counts); add_assoc_zval(hp_globals.stats_count, symbol->val, counts); - /*if (Z_REFCOUNTED_P(counts)) { - Z_ADDREF_P(counts); - } - //zend_hash_add_new(Z_ARRVAL_P(hp_globals.stats_count), zend_string_copy(symbol), counts); - zend_hash_update(Z_ARRVAL_P(hp_globals.stats_count), zend_string_dup(symbol, 0), counts);*/ } return counts; @@ -1675,7 +1670,7 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { hp_inc_count(counts, zend_string_init("pmu", sizeof("pmu") - 1, 1), pmu_end - top->pmu_start_hprof TSRMLS_CC); } - efree(counts); + //efree(counts); zend_string_free(symbol); } From 3dab7bb18e995ddf694d7934fe130e414bedfea1 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 6 Sep 2015 11:38:49 +0800 Subject: [PATCH 25/45] big change. no memleaks --- extension/xhprof.c | 97 +++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 53466e83..5d71eebe 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -504,11 +504,6 @@ PHP_MINIT_FUNCTION(xhprof) { srand(0); #endif - _zend_execute_internal = zend_execute_internal; - zend_execute_internal = hp_execute_internal; - - _zend_execute_ex = zend_execute_ex; - zend_execute_ex = hp_execute_ex; return SUCCESS; } @@ -531,6 +526,12 @@ PHP_MSHUTDOWN_FUNCTION(xhprof) { * Request init callback. Nothing to do yet! */ PHP_RINIT_FUNCTION(xhprof) { + _zend_execute_internal = zend_execute_internal; + zend_execute_internal = hp_execute_internal; + + _zend_execute_ex = zend_execute_ex; + zend_execute_ex = hp_execute_ex; + return SUCCESS; } @@ -692,9 +693,8 @@ void hp_init_profiler_state(int level TSRMLS_DC) { /* Init stats_count */ if (hp_globals.stats_count) { - zval_dtor(hp_globals.stats_count); + //zval_dtor(hp_globals.stats_count); efree(hp_globals.stats_count); -// FREE_ZVAL(hp_globals.stats_count); } hp_globals.stats_count = (zval *)emalloc(sizeof(zval)); @@ -731,9 +731,8 @@ void hp_clean_profiler_state(TSRMLS_D) { if (hp_globals.stats_count) { Z_DELREF_P(hp_globals.stats_count); //zend_array_destroy(Z_ARRVAL_P(hp_globals.stats_count)); - //efree(hp_globals.stats_count); - //FREE_ZVAL(hp_globals.stats_count); - //hp_globals.stats_count = NULL; + efree(hp_globals.stats_count); + hp_globals.stats_count = NULL; } hp_globals.entries = NULL; hp_globals.profiler_level = 1; @@ -1140,32 +1139,32 @@ void hp_inc_count(zval *counts, zend_string *name, long count TSRMLS_DC) { * * @author kannan, veeve */ -zval * hp_hash_lookup(zend_string *symbol TSRMLS_DC) { - HashTable *ht; - zval *data; - zval *counts; - - /* Bail if something is goofy */ - if (!hp_globals.stats_count || !(ht = HASH_OF(hp_globals.stats_count))) { - return (zval *) 0; - } - - /* Lookup our hash table */ - //zend_hash_str_find - if ((data = zend_hash_str_find(ht, symbol->val, strlen(symbol->val))) != NULL) { - /* Symbol already exists */ - counts = data; - } - else { - /* Add symbol to hash table */ - // MAKE_STD_ZVAL(counts); - counts = (zval *)emalloc(sizeof(zval)); - array_init(counts); - add_assoc_zval(hp_globals.stats_count, symbol->val, counts); - } - - return counts; -} +//zval * hp_hash_lookup(zend_string *symbol TSRMLS_DC) { +// HashTable *ht; +// zval *data; +// zval counts; +// +// /* Bail if something is goofy */ +// if (!hp_globals.stats_count || !(ht = HASH_OF(hp_globals.stats_count))) { +// return (zval *) 0; +// } +// +// /* Lookup our hash table */ +// //zend_hash_str_find +// if ((data = zend_hash_str_find(ht, symbol->val, strlen(symbol->val))) != NULL) { +// /* Symbol already exists */ +// counts = data; +// } +// else { +// /* Add symbol to hash table */ +// // MAKE_STD_ZVAL(counts); +// //counts = (zval *)emalloc(sizeof(zval)); +// array_init(&counts); +// add_assoc_zval(hp_globals.stats_count, symbol->val, &counts); +// } +// +// return (counts); +//} /** * Truncates the given timeval to the nearest slot begin, where @@ -1605,23 +1604,34 @@ void hp_mode_sampled_beginfn_cb(hp_entry_t **entries, */ zval * hp_mode_shared_endfn_cb(hp_entry_t *top, zend_string *symbol TSRMLS_DC) { - zval *counts; + zval counts; + zval *countsp; uint64 tsc_end; + HashTable *ht; /* Get end tsc counter */ tsc_end = cycle_timer(); /* Get the stat array */ - if (!(counts = hp_hash_lookup(symbol TSRMLS_CC))) { + /* Bail if something is goofy */ + if (!hp_globals.stats_count || !(ht = HASH_OF(hp_globals.stats_count))) { return (zval *) 0; } + /* Lookup our hash table */ + if ((countsp = zend_hash_str_find(ht, symbol->val, strlen(symbol->val))) == NULL) { + /* Add symbol to hash table */ + countsp = &counts; + array_init(countsp); + add_assoc_zval(hp_globals.stats_count, symbol->val, countsp); + } + /* Bump stats in the counts hashtable */ - hp_inc_count(counts, zend_string_init("ct", sizeof("ct") - 1, 1), 1 TSRMLS_CC); + hp_inc_count(countsp, zend_string_init("ct", sizeof("ct") - 1, 1), 1 TSRMLS_CC); - hp_inc_count(counts, zend_string_init("wt", sizeof("wt") - 1, 1), get_us_from_tsc(tsc_end - top->tsc_start, + hp_inc_count(countsp, zend_string_init("wt", sizeof("wt") - 1, 1), get_us_from_tsc(tsc_end - top->tsc_start, hp_globals.cpu_frequencies[hp_globals.cur_cpu_id]) TSRMLS_CC); - return counts; + return countsp; } /** @@ -1646,7 +1656,8 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { efree(symbol); return; } - + zend_string_free(symbol); + return; if (hp_globals.xhprof_flags & XHPROF_FLAGS_CPU) { /* Get CPU usage */ getrusage(RUSAGE_SELF, &ru_end); @@ -1670,8 +1681,6 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { hp_inc_count(counts, zend_string_init("pmu", sizeof("pmu") - 1, 1), pmu_end - top->pmu_start_hprof TSRMLS_CC); } - //efree(counts); - zend_string_free(symbol); } /** From a292de7ad38fbc6bb245724bf2111245f0881f08 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 6 Sep 2015 11:53:42 +0800 Subject: [PATCH 26/45] fixed a big big bug --- extension/xhprof.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 5d71eebe..9f040744 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -271,7 +271,6 @@ static void (*_zend_execute_ex) (zend_execute_data *execute_data TSRMLS_DC); /* Pointer to the origianl execute_internal function */ static void (*_zend_execute_internal) (zend_execute_data *data, zval *ret TSRMLS_DC); -#define EX_T(offset) (*EX_TMP_VAR(execute_data, offset)) ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval* ret TSRMLS_DC); @@ -540,6 +539,8 @@ PHP_RINIT_FUNCTION(xhprof) { */ PHP_RSHUTDOWN_FUNCTION(xhprof) { hp_end(TSRMLS_C); + zend_execute_ex = _zend_execute_ex; + zend_execute_internal = _zend_execute_internal; return SUCCESS; } @@ -821,7 +822,7 @@ size_t hp_get_entry_name(hp_entry_t *entry, /* Add '@recurse_level' if required */ /* NOTE: Dont use snprintf's return val as it is compiler dependent */ if (entry->rlvl_hprof) { - snprintf(result->val, result->len, + snprintf(result->val+strlen(result->val), result->len, "%s@%d", entry->name_hprof->val, entry->rlvl_hprof); } @@ -1738,7 +1739,6 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { */ -#define EX_T(offset) (*EX_TMP_VAR(execute_data, offset)) ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *ret TSRMLS_DC) { zend_execute_data *current_data; @@ -1925,8 +1925,6 @@ static void hp_stop(TSRMLS_D) { } /* Remove proxies, restore the originals */ - zend_execute_ex = _zend_execute_ex; - zend_execute_internal = _zend_execute_internal; //zend_compile_file = _zend_compile_file; //zend_compile_string = _zend_compile_string; From ffab5d9e86735fbd23e07f250d68d7b0f0837907 Mon Sep 17 00:00:00 2001 From: sunan <327369214@qq.com> Date: Thu, 10 Sep 2015 00:28:28 +0800 Subject: [PATCH 27/45] add class --- extension/xhprof.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 9f040744..e73266dd 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -730,7 +730,8 @@ void hp_clean_profiler_state(TSRMLS_D) { /* Clear globals */ if (hp_globals.stats_count) { - Z_DELREF_P(hp_globals.stats_count); + //Z_DELREF_P(hp_globals.stats_count); + zval_ptr_dtor(hp_globals.stats_count); //zend_array_destroy(Z_ARRVAL_P(hp_globals.stats_count)); efree(hp_globals.stats_count); hp_globals.stats_count = NULL; @@ -1713,8 +1714,20 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { zend_string *func = NULL; int hp_profile_flag = 1; - //func = hp_get_function_name(ops TSRMLS_CC); func = execute_data->func->internal_function.function_name; + if (execute_data ->This.value.obj != NULL) { + //this is a class method; + zend_string *class_name = execute_data->This.value.obj->ce->name; + zend_string *func_name = func; + + int class_name_len = class_name->len; + func = zend_string_init(class_name->val, class_name_len + 2 + func_name->len, 0); + memcpy(func->val + class_name_len, "::", 2); + memcpy(func->val + class_name_len + 2, func_name->val, func_name->len); + } else if (func) { + //just do the copy; + func = zend_string_init(func->val, func->len, 0); + } if (!func) { _zend_execute_ex(execute_data TSRMLS_CC); return; @@ -1725,7 +1738,10 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { if (hp_globals.entries) { END_PROFILING(&hp_globals.entries, hp_profile_flag); } - //zend_string_free(func); + if (func) { + + zend_string_free(func); + } } #undef EX From d612b2cdf6621728b52d1befe17b596edec5eb46 Mon Sep 17 00:00:00 2001 From: sunan <327369214@qq.com> Date: Thu, 10 Sep 2015 00:40:11 +0800 Subject: [PATCH 28/45] fix class inhired class name --- extension/xhprof.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index e73266dd..c654c9a9 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -1717,7 +1717,7 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { func = execute_data->func->internal_function.function_name; if (execute_data ->This.value.obj != NULL) { //this is a class method; - zend_string *class_name = execute_data->This.value.obj->ce->name; + zend_string *class_name = execute_data->func ->common.scope ->name; zend_string *func_name = func; int class_name_len = class_name->len; From 68bd7d8dfacda079d13465d2099bef420aa55344 Mon Sep 17 00:00:00 2001 From: sunan <327369214@qq.com> Date: Thu, 10 Sep 2015 00:45:01 +0800 Subject: [PATCH 29/45] delete unused code, and nolonger suppor sample --- extension/xhprof.c | 268 --------------------------------------------- 1 file changed, 268 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index c654c9a9..3459fdf0 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -317,11 +317,6 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_xhprof_disable, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_xhprof_sample_enable, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_xhprof_sample_disable, 0) -ZEND_END_ARG_INFO() /* }}} */ /** @@ -341,8 +336,6 @@ int bind_to_cpu(uint32 cpu_id); zend_function_entry xhprof_functions[] = { PHP_FE(xhprof_enable, arginfo_xhprof_enable) PHP_FE(xhprof_disable, arginfo_xhprof_disable) - PHP_FE(xhprof_sample_enable, arginfo_xhprof_sample_enable) - PHP_FE(xhprof_sample_disable, arginfo_xhprof_sample_disable) {NULL, NULL, NULL} }; @@ -423,33 +416,7 @@ PHP_FUNCTION(xhprof_disable) { /* else null is returned */ } -/** - * Start XHProf profiling in sampling mode. - * - * @return void - * @author cjiang - */ -PHP_FUNCTION(xhprof_sample_enable) { - long xhprof_flags = 0; /* XHProf flags */ - hp_get_ignored_functions_from_arg(NULL); - hp_begin(XHPROF_MODE_SAMPLED, xhprof_flags TSRMLS_CC); -} -/** - * Stops XHProf from profiling in sampling mode anymore and returns the profile - * info. - * - * @param void - * @return array hash-array of XHProf's profile info - * @author cjiang - */ -PHP_FUNCTION(xhprof_sample_disable) { - if (hp_globals.enabled) { - hp_stop(TSRMLS_C); - RETURN_ZVAL(hp_globals.stats_count, 1, 0); - } - /* else null is returned */ -} /** * Module init callback. @@ -949,112 +916,6 @@ static const char *hp_get_base_filename(const char *filename) { return filename; } -/** - * Get the name of the current function. The name is qualified with - * the class name if the function is in a class. - * - * @author kannan, hzhao - */ -static char *hp_get_function_name(zend_op_array *ops TSRMLS_DC) { - zend_execute_data *data; - const char *func = NULL; - const char *cls = NULL; - char *ret = NULL; - int len; - zend_function *curr_func; - - data = EG(current_execute_data); - - if (data) { - /* shared meta data for function on the call stack */ - curr_func = data->func; - - /* extract function name from the meta info */ - func = curr_func->common.function_name->val; - - if (func) { - /* previously, the order of the tests in the "if" below was - * flipped, leading to incorrect function names in profiler - * reports. When a method in a super-type is invoked the - * profiler should qualify the function name with the super-type - * class name (not the class name based on the run-time type - * of the object. - */ - if (curr_func->common.scope) { - cls = curr_func->common.scope->name->val; - } else if (data->called_scope) { - cls = data->called_scope->name->val; - } - - if (cls) { - len = strlen(cls) + strlen(func) + 10; - ret = (char*)emalloc(len); - snprintf(ret, len, "%s::%s", cls, func); - } else { - ret = estrdup(func); - } - } else { - long curr_op; - int add_filename = 0; - - /* we are dealing with a special directive/function like - * include, eval, etc. - */ -#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; -#endif - - switch (curr_op) { - case ZEND_EVAL: - func = "eval"; - break; - case ZEND_INCLUDE: - func = "include"; - add_filename = 1; - break; - case ZEND_REQUIRE: - func = "require"; - add_filename = 1; - break; - case ZEND_INCLUDE_ONCE: - func = "include_once"; - add_filename = 1; - break; - case ZEND_REQUIRE_ONCE: - func = "require_once"; - add_filename = 1; - break; - default: - func = "???_op"; - break; - } - - /* For some operations, we'll add the filename as part of the function - * name to make the reports more useful. So rather than just "include" - * you'll see something like "run_init::foo.php" in your reports. - */ - if (add_filename){ - const char *filename; - int len; - filename = hp_get_base_filename((curr_func->op_array).filename->val); - len = strlen("run_init") + strlen(filename) + 3; - ret = (char *)emalloc(len); - snprintf(ret, len, "run_init::%s", filename); - } else { - ret = estrdup(func); - } - } - } - return ret; -} /** * Free any items in the free list. @@ -1191,73 +1052,6 @@ void hp_trunc_time(struct timeval *tv, tv->tv_usec = (time_in_micro % 1000000); } -/** - * Sample the stack. Add it to the stats_count global. - * - * @param tv current time - * @param entries func stack as linked list of hp_entry_t - * @return void - * @author veeve - */ -void hp_sample_stack(hp_entry_t **entries TSRMLS_DC) { - -// //char symbol[SCRATCH_BUF_LEN * 1000]; -// zend_string *symbol; -// zend_string *key; -// symbol = zend_string_alloc(SCRATCH_BUF_LEN * 1000, 0); -// key = zend_string_alloc(SCRATCH_BUF_LEN, 0); -// -// /* Build key */ -// snprintf(key->val, key->len, -// "%d.%06d", -// hp_globals.last_sample_time.tv_sec, -// hp_globals.last_sample_time.tv_usec); -// -// /* Init stats in the global stats_count hashtable */ -// hp_get_function_stack(*entries, -// INT_MAX, -// symbol -// ); -// -// add_assoc_string(hp_globals.stats_count, -// key->val, -// symbol->val); -// return; -} - -/** - * Checks to see if it is time to sample the stack. - * Calls hp_sample_stack() if its time. - * - * @param entries func stack as linked list of hp_entry_t - * @param last_sample time the last sample was taken - * @param sampling_intr sampling interval in microsecs - * @return void - * @author veeve - */ -void hp_sample_check(hp_entry_t **entries TSRMLS_DC) { - /* Validate input */ - if (!entries || !(*entries)) { - return; - } - - /* See if its time to sample. While loop is to handle a single function - * taking a long time and passing several sampling intervals. */ - while ((cycle_timer() - hp_globals.last_sample_tsc) - > hp_globals.sampling_interval_tsc) { - - /* bump last_sample_tsc */ - hp_globals.last_sample_tsc += hp_globals.sampling_interval_tsc; - - /* bump last_sample_time - HAS TO BE UPDATED BEFORE calling hp_sample_stack */ - incr_us_interval(&hp_globals.last_sample_time, XHPROF_SAMPLING_INTERVAL); - - /* sample the stack */ - hp_sample_stack(entries TSRMLS_CC); - } - - return; -} /** @@ -1514,42 +1308,6 @@ void hp_mode_common_endfn(hp_entry_t **entries, hp_entry_t *current TSRMLS_DC) { } -/** - * ********************************* - * XHPROF INIT MODULE CALLBACKS - * ********************************* - */ -/** - * XHPROF_MODE_SAMPLED's init callback - * - * @author veeve - */ -void hp_mode_sampled_init_cb(TSRMLS_D) { - struct timeval now; - uint64 truncated_us; - uint64 truncated_tsc; - double cpu_freq = hp_globals.cpu_frequencies[hp_globals.cur_cpu_id]; - - /* Init the last_sample in tsc */ - hp_globals.last_sample_tsc = cycle_timer(); - - /* Find the microseconds that need to be truncated */ - gettimeofday(&hp_globals.last_sample_time, 0); - now = hp_globals.last_sample_time; - hp_trunc_time(&hp_globals.last_sample_time, XHPROF_SAMPLING_INTERVAL); - - /* Subtract truncated time from last_sample_tsc */ - truncated_us = get_us_interval(&hp_globals.last_sample_time, &now); - truncated_tsc = get_tsc_from_us(truncated_us, cpu_freq); - if (hp_globals.last_sample_tsc > truncated_tsc) { - /* just to be safe while subtracting unsigned ints */ - hp_globals.last_sample_tsc -= truncated_tsc; - } - - /* Convert sampling interval to ticks */ - hp_globals.sampling_interval_tsc = - get_tsc_from_us(XHPROF_SAMPLING_INTERVAL, cpu_freq); -} /** @@ -1581,16 +1339,6 @@ void hp_mode_hier_beginfn_cb(hp_entry_t **entries, } -/** - * XHPROF_MODE_SAMPLED's begin function callback - * - * @author veeve - */ -void hp_mode_sampled_beginfn_cb(hp_entry_t **entries, - hp_entry_t *current TSRMLS_DC) { - /* See if its time to take a sample */ - hp_sample_check(entries TSRMLS_CC); -} /** @@ -1685,16 +1433,6 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { } -/** - * XHPROF_MODE_SAMPLED's end function callback - * - * @author veeve - */ -void hp_mode_sampled_endfn_cb(hp_entry_t **entries TSRMLS_DC) { - /* See if its time to take a sample */ - hp_sample_check(entries TSRMLS_CC); -} - /** * *************************** @@ -1762,7 +1500,6 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re int hp_profile_flag = 1; current_data = EG(current_execute_data); - //func = hp_get_function_name(¤t_data->func->op_array TSRMLS_CC); func = current_data->func->op_array.function_name ; if (func && strcmp("xhprof_enable", func->val) != 0) { @@ -1868,11 +1605,6 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { hp_globals.mode_cb.begin_fn_cb = hp_mode_hier_beginfn_cb; hp_globals.mode_cb.end_fn_cb = hp_mode_hier_endfn_cb; break; - case XHPROF_MODE_SAMPLED: - hp_globals.mode_cb.init_cb = hp_mode_sampled_init_cb; - hp_globals.mode_cb.begin_fn_cb = hp_mode_sampled_beginfn_cb; - hp_globals.mode_cb.end_fn_cb = hp_mode_sampled_endfn_cb; - break; } BEGIN_PROFILING(&hp_globals.entries, zend_string_init(ROOT_SYMBOL, sizeof(ROOT_SYMBOL) - 1, 1), hp_profile_flag); /* return here or recu*/ From 478145c157cb1c0e4468b1f9afcde5d9c0be30f0 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 10 Sep 2015 11:08:30 +0800 Subject: [PATCH 30/45] stop prof after disable --- extension/xhprof.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extension/xhprof.c b/extension/xhprof.c index 3459fdf0..9f86209d 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -1672,6 +1672,8 @@ static void hp_stop(TSRMLS_D) { END_PROFILING(&hp_globals.entries, hp_profile_flag); } + zend_execute_ex = _zend_execute_ex; + zend_execute_internal = _zend_execute_internal; /* Remove proxies, restore the originals */ //zend_compile_file = _zend_compile_file; //zend_compile_string = _zend_compile_string; From 8b589527d37955090e7a25ab3acd976786e15253 Mon Sep 17 00:00:00 2001 From: Jason Young <327369214@qq.com> Date: Mon, 9 Nov 2015 17:10:16 +0800 Subject: [PATCH 31/45] Fix static class error --- extension/xhprof.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 9f86209d..f6d20ef8 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -1453,9 +1453,10 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { int hp_profile_flag = 1; func = execute_data->func->internal_function.function_name; - if (execute_data ->This.value.obj != NULL) { + /* check if was in a class */ + if (execute_data ->called_scope != NULL) { //this is a class method; - zend_string *class_name = execute_data->func ->common.scope ->name; + zend_string *class_name = execute_data->called_scope ->name; zend_string *func_name = func; int class_name_len = class_name->len; From 69ce1015d12547fe96de977b6d28a0c349ec006e Mon Sep 17 00:00:00 2001 From: Jason Young <327369214@qq.com> Date: Mon, 9 Nov 2015 20:04:48 +0800 Subject: [PATCH 32/45] Add require suppor --- extension/tests/tags | 1 + extension/tests/xhprof_006.phpt | 78 --------------------------------- extension/tests/xhprof_008.phpt | 75 ------------------------------- extension/xhprof.c | 43 +++++++++--------- 4 files changed, 22 insertions(+), 175 deletions(-) create mode 100644 extension/tests/tags delete mode 100644 extension/tests/xhprof_006.phpt delete mode 100644 extension/tests/xhprof_008.phpt diff --git a/extension/tests/tags b/extension/tests/tags new file mode 100644 index 00000000..408de88a --- /dev/null +++ b/extension/tests/tags @@ -0,0 +1 @@ +!_TAG_FILE_SORTED 2 /0=unsorted, 1=sorted, 2=foldcase/ diff --git a/extension/tests/xhprof_006.phpt b/extension/tests/xhprof_006.phpt deleted file mode 100644 index d8ac65b0..00000000 --- a/extension/tests/xhprof_006.phpt +++ /dev/null @@ -1,78 +0,0 @@ ---TEST-- -XHProf: Basic Sampling Test -Author: mpal ---FILE-- - ---EXPECT-- -Part 1: Sampling Profile -Test Case : Percent of Total Time -Individual : -Folded : -Part 1: output -In general, sampling output depends upon execution speed. -Currently checking that this runs to completion. - diff --git a/extension/tests/xhprof_008.phpt b/extension/tests/xhprof_008.phpt deleted file mode 100644 index e62849f1..00000000 --- a/extension/tests/xhprof_008.phpt +++ /dev/null @@ -1,75 +0,0 @@ ---TEST-- -XHProf: Sampling Mode Test -Author: kannan ---FILE-- -goo==>bar==>foo==>usleep") { - $count1++; - } -} - -// how many usleep samples did we get in two calls to goo()? -$count2 = 0; -foreach ($output2 as $sample) { - if ($sample == "main()==>goo==>bar==>foo==>usleep") { - $count2++; - } -} - -// -// our default sampling frequency is 0.1 seconds. So -// we would expect about 8 samples (given that foo() -// sleeps for 0.8 seconds). However, we might in future -// allow the sampling frequency to be modified. So rather -// than depend on the absolute number of samples, we'll -// check to see if $count2 is roughly double of $count1. -// - -if (($count1 == 0) - || (($count2 / $count1) > 2.5) - || (($count2 / $count1) < 1.5)) { - echo "Test failed\n"; - echo "Count of usleep samples in one call to goo(): $count1\n"; - echo "Count of usleep samples in two calls to goo(): $count2\n"; - echo "Samples in one call to goo(): \n"; - var_dump($output1); - echo "Samples in two calls to goo(): \n"; - var_dump($output2); -} else { - echo "Test passed\n"; -} - -?> ---EXPECT-- -Test passed diff --git a/extension/xhprof.c b/extension/xhprof.c index f6d20ef8..39c74096 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -276,6 +276,7 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval* re ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC); +ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC); /** * **************************** * STATIC FUNCTION DECLARATIONS @@ -497,7 +498,10 @@ PHP_RINIT_FUNCTION(xhprof) { _zend_execute_ex = zend_execute_ex; zend_execute_ex = hp_execute_ex; - + + _zend_compile_file = zend_compile_file; + zend_compile_file = hp_compile_file; + return SUCCESS; } @@ -508,6 +512,8 @@ PHP_RSHUTDOWN_FUNCTION(xhprof) { hp_end(TSRMLS_C); zend_execute_ex = _zend_execute_ex; zend_execute_internal = _zend_execute_internal; + + zend_compile_file = _zend_compile_file; return SUCCESS; } @@ -1468,7 +1474,7 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { func = zend_string_init(func->val, func->len, 0); } if (!func) { - _zend_execute_ex(execute_data TSRMLS_CC); + _zend_execute_ex(execute_data TSRMLS_CC); return; } @@ -1535,25 +1541,27 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) { - /*const char *filename; - char *func; + const char *filename; int len; zend_op_array *ret; int hp_profile_flag = 1; + zend_string *func_name; filename = hp_get_base_filename(file_handle->filename); len = strlen("load") + strlen(filename) + 3; - func = (char *)emalloc(len); - snprintf(func, len, "load::%s", filename); - BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag); + func_name = zend_string_init(filename, len, 0); + + snprintf(func_name->val, len, "load::%s", filename); + + BEGIN_PROFILING(&hp_globals.entries, func_name, hp_profile_flag); ret = _zend_compile_file(file_handle, type TSRMLS_CC); if (hp_globals.entries) { END_PROFILING(&hp_globals.entries, hp_profile_flag); } - efree(func); - return ret;*/ + zend_string_free(func_name); + return ret; } /** @@ -1611,7 +1619,7 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { /* return here or recu*/ return; - /* Replace zend_compile with our proxy */ + /* Replace zend_compile_file with our proxy */ _zend_compile_file = zend_compile_file; zend_compile_file = hp_compile_file; @@ -1620,7 +1628,6 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { zend_compile_string = hp_compile_string; /* Replace zend_execute with our proxy */ - _zend_execute_ex = zend_execute_ex; zend_execute_ex = hp_execute_ex; @@ -1634,7 +1641,6 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { } - /* one time initializations */ hp_init_profiler_state(level TSRMLS_CC); @@ -1675,9 +1681,10 @@ static void hp_stop(TSRMLS_D) { zend_execute_ex = _zend_execute_ex; zend_execute_internal = _zend_execute_internal; + /* Remove proxies, restore the originals */ - //zend_compile_file = _zend_compile_file; - //zend_compile_string = _zend_compile_string; + zend_compile_file = _zend_compile_file; + zend_compile_string = _zend_compile_string; /* Resore cpu affinity. */ restore_cpu_affinity(&hp_globals.prev_mask); @@ -1793,11 +1800,3 @@ static inline void hp_array_del(char **name_array) { // efree(name_array); // } } -/*inline int xhprof_icall_handler(zend_execute_data *execute_data) { - zend_op *opline = execute_data->opline; - - php_printf("before\n"); -// zend_opcode_handlers[opline->opcode + 1](execute_data); - php_printf("after\n"); - return ZEND_USER_OPCODE_DISPATCH; -}*/ From 6f59ef0a938d6997c49053bf56e7f089009c1cb2 Mon Sep 17 00:00:00 2001 From: Jason Young <327369214@qq.com> Date: Mon, 9 Nov 2015 20:13:41 +0800 Subject: [PATCH 33/45] Remove ignore support --- extension/tests/xhprof_007.phpt | 274 -------------------------------- extension/xhprof.c | 2 +- 2 files changed, 1 insertion(+), 275 deletions(-) delete mode 100644 extension/tests/xhprof_007.phpt diff --git a/extension/tests/xhprof_007.phpt b/extension/tests/xhprof_007.phpt deleted file mode 100644 index 1afdd3de..00000000 --- a/extension/tests/xhprof_007.phpt +++ /dev/null @@ -1,274 +0,0 @@ ---TEST-- -XHProf: Test excluding call_user_func and similar functions -Author: mpal ---FILE-- - - array('call_user_func', - 'call_user_func_array', - 'my_call_user_func_safe', - 'my_call_user_func_array_safe')); -function bar() { - return 1; -} - -function foo($x) { - $sum = 0; - for ($idx = 0; $idx < 2; $idx++) { - $sum += bar(); - } - echo @"hello: {$x}\n" ; - return @strlen("hello: {$x}"); -} - -function foo_array($x1, $x2 = 'test') { - $sum = 0; - $x = array($x1, $x2); - foreach ($x as $idx) { - $sum += bar(); - } - echo @"hello: {$x[0]}{$x[1]}\n"; - return @strlen("hello: {$x[0]} {$x[1]}"); -} - -function my_call_user_func_safe($function, $args = 'my_safe') { - if (!is_callable($function, true)) { - throw new Exception('my_call_user_func_safe() invoked without ' . - 'a valid callable.'); - } - - call_user_func($function, array($args)); -} - -function my_call_user_func_array_safe($function, $args = array()) { - if (!is_callable($function, true)) { - throw new Exception('my_call_user_func_array_safe() invoked without ' . - 'a valid callable.'); - } - - call_user_func_array($function, $args); -} - - -class test_call_user_func { - function test_call_user_func($test_func = 'foo', - $arg1 = 'user_func test') { - call_user_func($test_func, $arg1); - } -} - -function test_call_user_func_array($test_func = 'foo_array', - $arg1 = array(0 => 'user_func_array', - 'test')) { - call_user_func_array($test_func, $arg1); -} - -function test_my_call_user_func_safe($test_func = 'foo', - $arg1 = 'my_user_func_safe test') { - my_call_user_func_safe($test_func, $arg1); -} - -function test_my_call_user_func_array_safe( - $test_func = 'foo_array', - $arg1 = array('my_user_func_array_safe', - 'test')) { - my_call_user_func_array_safe($test_func, $arg1); -} - - -// 1: Sanity test a simple profile run -echo "Part 1: Default Flags\n"; -xhprof_enable(0, $xhprof_ignored_functions); -foo("this is a test"); -$array_arg = array(); -$array_arg[] = 'calling '; -$array_arg[] = 'foo_array'; -foo_array($array_arg); - -$output = xhprof_disable(); -echo "Part 1 output:\n"; -print_canonical($output); -echo "\n"; - -// 2a: Sanity test ignoring call_user_func -echo "Part 2a: Ignore call_user_func\n"; -xhprof_enable(0, $xhprof_ignored_functions); -$indirect_foo = new test_call_user_func('foo'); -$output = xhprof_disable(); -echo "Part 2a output:\n"; -print_canonical($output); -echo "\n"; - -// 2b: Confirm that profiling without parameters still works -echo "Part 2b: Standard profile without parameters\n"; -xhprof_enable(); -$indirect_foo = new test_call_user_func('foo'); -$output = xhprof_disable(); -echo "Part 2b output:\n"; -print_canonical($output); -echo "\n"; - -// 2c: Confirm that empty array of ignored functions works -echo "Part 2c: Standard profile with empty array of ignored functions\n"; -xhprof_enable(0, array()); -$indirect_foo = new test_call_user_func('foo'); -$output = xhprof_disable(); -echo "Part 2c output:\n"; -print_canonical($output); -echo "\n"; - -// 3: Sanity test ignoring call_user_func_array -echo "Part 3: Ignore call_user_func_array\n"; -xhprof_enable(XHPROF_FLAGS_CPU, $xhprof_ignored_functions); -test_call_user_func_array('foo_array', $array_arg); -$output = xhprof_disable(); -echo "Part 3 output:\n"; -print_canonical($output); -echo "\n"; - -// 4: Sanity test ignoring my_call_user_func_safe -echo "Part 4: Ignore my_call_user_func_safe\n"; -xhprof_enable(0, $xhprof_ignored_functions); -test_my_call_user_func_safe('foo'); -$output = xhprof_disable(); -echo "Part 4 output:\n"; -print_canonical($output); -echo "\n"; - -// 5a: Sanity test ignoring my_call_user_func_array_safe and strlen -echo "Part 5a: Ignore my_call_user_func_array_safe and strlen\n"; -$tmp1 = $xhprof_ignored_functions['ignored_functions']; -$tmp1[] = 'strlen'; -$ignore_strlen_also = array('ignored_functions' => $tmp1); -xhprof_enable(XHPROF_FLAGS_MEMORY, $ignore_strlen_also); -test_my_call_user_func_array_safe('foo_array'); -$output = xhprof_disable(); -echo "Part 5a output:\n"; -print_canonical($output); -echo "\n"; - -// 5b: Sanity test to not ignore call_user_func variants -echo "Part 5b: Profile call_user_func_array and my_call_user_func_array_safe\n"; -xhprof_enable(XHPROF_FLAGS_MEMORY, array()); -test_my_call_user_func_array_safe('foo_array'); -$output = xhprof_disable(); -echo "Part 5b output:\n"; -print_canonical($output); -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' => - 'my_call_user_func_array_safe'); -xhprof_enable(XHPROF_FLAGS_MEMORY, $xhprof_ignored_functions); -test_my_call_user_func_array_safe('foo_array'); -$output = xhprof_disable(); -echo "Part 5c output:\n"; -print_canonical($output); -echo "\n"; - -?> ---EXPECT-- -Part 1: Default Flags -hello: this is a test -hello: Arraytest -Part 1 output: -foo==>bar : ct= 2; wt=*; -foo==>strlen : ct= 1; wt=*; -foo_array==>bar : ct= 2; wt=*; -foo_array==>strlen : ct= 1; wt=*; -main() : ct= 1; wt=*; -main()==>foo : ct= 1; wt=*; -main()==>foo_array : ct= 1; wt=*; -main()==>xhprof_disable : ct= 1; wt=*; - -Part 2a: Ignore call_user_func -hello: user_func test -Part 2a output: -foo==>bar : ct= 2; wt=*; -foo==>strlen : ct= 1; wt=*; -main() : ct= 1; wt=*; -main()==>test_call_user_func::test_call_user_func: ct= 1; wt=*; -main()==>xhprof_disable : ct= 1; wt=*; -test_call_user_func::test_call_user_func==>foo: ct= 1; wt=*; - -Part 2b: Standard profile without parameters -hello: user_func test -Part 2b output: -call_user_func==>foo : ct= 1; wt=*; -foo==>bar : ct= 2; wt=*; -foo==>strlen : ct= 1; wt=*; -main() : ct= 1; wt=*; -main()==>test_call_user_func::test_call_user_func: ct= 1; wt=*; -main()==>xhprof_disable : ct= 1; wt=*; -test_call_user_func::test_call_user_func==>call_user_func: ct= 1; wt=*; - -Part 2c: Standard profile with empty array of ignored functions -hello: user_func test -Part 2c output: -call_user_func==>foo : ct= 1; wt=*; -foo==>bar : ct= 2; wt=*; -foo==>strlen : ct= 1; wt=*; -main() : ct= 1; wt=*; -main()==>test_call_user_func::test_call_user_func: ct= 1; wt=*; -main()==>xhprof_disable : ct= 1; wt=*; -test_call_user_func::test_call_user_func==>call_user_func: ct= 1; wt=*; - -Part 3: Ignore call_user_func_array -hello: calling foo_array -Part 3 output: -foo_array==>bar : cpu=*; ct= 2; wt=*; -foo_array==>strlen : cpu=*; ct= 1; wt=*; -main() : cpu=*; ct= 1; wt=*; -main()==>test_call_user_func_array : cpu=*; ct= 1; wt=*; -main()==>xhprof_disable : cpu=*; ct= 1; wt=*; -test_call_user_func_array==>foo_array : cpu=*; ct= 1; wt=*; - -Part 4: Ignore my_call_user_func_safe -hello: Array -Part 4 output: -foo==>bar : ct= 2; wt=*; -foo==>strlen : ct= 1; wt=*; -main() : ct= 1; wt=*; -main()==>test_my_call_user_func_safe : ct= 1; wt=*; -main()==>xhprof_disable : ct= 1; wt=*; -test_my_call_user_func_safe==>foo : ct= 1; wt=*; -test_my_call_user_func_safe==>is_callable: ct= 1; wt=*; - -Part 5a: Ignore my_call_user_func_array_safe and strlen -hello: my_user_func_array_safetest -Part 5a output: -foo_array==>bar : ct= 2; mu=*; pmu=*; wt=*; -main() : ct= 1; mu=*; pmu=*; wt=*; -main()==>test_my_call_user_func_array_safe: ct= 1; mu=*; pmu=*; wt=*; -main()==>xhprof_disable : ct= 1; mu=*; pmu=*; wt=*; -test_my_call_user_func_array_safe==>foo_array: ct= 1; mu=*; pmu=*; wt=*; -test_my_call_user_func_array_safe==>is_callable: ct= 1; mu=*; pmu=*; wt=*; - -Part 5b: Profile call_user_func_array and my_call_user_func_array_safe -hello: my_user_func_array_safetest -Part 5b output: -call_user_func_array==>foo_array : ct= 1; mu=*; pmu=*; wt=*; -foo_array==>bar : ct= 2; mu=*; pmu=*; wt=*; -foo_array==>strlen : ct= 1; mu=*; pmu=*; wt=*; -main() : ct= 1; mu=*; pmu=*; wt=*; -main()==>test_my_call_user_func_array_safe: ct= 1; mu=*; pmu=*; wt=*; -main()==>xhprof_disable : ct= 1; mu=*; pmu=*; wt=*; -my_call_user_func_array_safe==>call_user_func_array: ct= 1; mu=*; pmu=*; wt=*; -my_call_user_func_array_safe==>is_callable: ct= 1; mu=*; pmu=*; wt=*; -test_my_call_user_func_array_safe==>my_call_user_func_array_safe: ct= 1; mu=*; pmu=*; wt=*; - -Part 5c: Only ignore call_user_func_array -hello: my_user_func_array_safetest -Part 5c output: -call_user_func_array==>foo_array : ct= 1; mu=*; pmu=*; wt=*; -foo_array==>bar : ct= 2; mu=*; pmu=*; wt=*; -foo_array==>strlen : ct= 1; mu=*; pmu=*; wt=*; -main() : ct= 1; mu=*; pmu=*; wt=*; -main()==>test_my_call_user_func_array_safe: ct= 1; mu=*; pmu=*; wt=*; -main()==>xhprof_disable : ct= 1; mu=*; pmu=*; wt=*; -test_my_call_user_func_array_safe==>call_user_func_array: ct= 1; mu=*; pmu=*; wt=*; -test_my_call_user_func_array_safe==>is_callable: ct= 1; mu=*; pmu=*; wt=*; diff --git a/extension/xhprof.c b/extension/xhprof.c index 39c74096..fe12a106 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -396,7 +396,7 @@ PHP_FUNCTION(xhprof_enable) { return; } - hp_get_ignored_functions_from_arg(optional_array); + //hp_get_ignored_functions_from_arg(optional_array); hp_begin(XHPROF_MODE_HIERARCHICAL, xhprof_flags TSRMLS_CC); } From be4a5fbd6dae15dab587f17f243145dcc09216a2 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Tue, 1 Dec 2015 16:11:46 +0800 Subject: [PATCH 34/45] Added run_init entry --- extension/xhprof.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/extension/xhprof.c b/extension/xhprof.c index fe12a106..b0385dc6 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -1472,7 +1472,17 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { } else if (func) { //just do the copy; func = zend_string_init(func->val, func->len, 0); + } else if (execute_data->literals->u1.type_info == 4) { + + //could include, not sure others has the same value + //This is fucking dam ugly + zend_string *filename = execute_data->func->op_array.filename; + + int run_init_len = sizeof("run_init::") - 1; + func = zend_string_init("run_init::", run_init_len + filename->len, 0); + memcpy(func->val + run_init_len, filename->val, filename->len); } + if (!func) { _zend_execute_ex(execute_data TSRMLS_CC); return; From 6d90a2ce6563c333260db37941831bfafd54b2fd Mon Sep 17 00:00:00 2001 From: Jason Young Date: Tue, 1 Dec 2015 19:40:39 +0800 Subject: [PATCH 35/45] Back up, memleaks during rec --- extension/xhprof.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index b0385dc6..aee235eb 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -933,7 +933,7 @@ static void hp_free_the_free_list() { while (p) { cur = p; p = p->prev_hprof; - free(cur); + efree(cur); } } @@ -954,7 +954,7 @@ static hp_entry_t *hp_fast_alloc_hprof_entry() { hp_globals.entry_free_list = p->prev_hprof; return p; } else { - return (hp_entry_t *)malloc(sizeof(hp_entry_t)); + return (hp_entry_t *)emalloc(sizeof(hp_entry_t)); } } @@ -1460,10 +1460,10 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { func = execute_data->func->internal_function.function_name; /* check if was in a class */ - if (execute_data ->called_scope != NULL) { + if (execute_data ->called_scope != NULL && func != NULL) { //this is a class method; zend_string *class_name = execute_data->called_scope ->name; - zend_string *func_name = func; + zend_string *func_name = func; int class_name_len = class_name->len; func = zend_string_init(class_name->val, class_name_len + 2 + func_name->len, 0); @@ -1558,11 +1558,11 @@ ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, zend_string *func_name; filename = hp_get_base_filename(file_handle->filename); - len = strlen("load") + strlen(filename) + 3; + len = strlen("load::") + strlen(filename); func_name = zend_string_init(filename, len, 0); - snprintf(func_name->val, len, "load::%s", filename); + snprintf(func_name->val, len + 1, "load::%s", filename); BEGIN_PROFILING(&hp_globals.entries, func_name, hp_profile_flag); ret = _zend_compile_file(file_handle, type TSRMLS_CC); From e94a189645a29f8eace4eb03773f5196ce6652f1 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Wed, 2 Dec 2015 12:11:11 +0800 Subject: [PATCH 36/45] Fixed a Seg --- extension/xhprof.c | 54 +++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index aee235eb..1e1da274 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -493,15 +493,22 @@ PHP_MSHUTDOWN_FUNCTION(xhprof) { * Request init callback. Nothing to do yet! */ PHP_RINIT_FUNCTION(xhprof) { + + _zend_compile_file = zend_compile_file; + zend_compile_file = hp_compile_file; + + /* Replace zend_compile_string with our proxy */ + //_zend_compile_string = zend_compile_string; + //zend_compile_string = hp_compile_string; + + /* Replace zend_execute with our proxy */ + _zend_execute_ex = zend_execute_ex; + zend_execute_ex = hp_execute_ex; + + /* Replace zend_execute_internal with our proxy */ _zend_execute_internal = zend_execute_internal; zend_execute_internal = hp_execute_internal; - - _zend_execute_ex = zend_execute_ex; - zend_execute_ex = hp_execute_ex; - - _zend_compile_file = zend_compile_file; - zend_compile_file = hp_compile_file; - + return SUCCESS; } @@ -933,7 +940,7 @@ static void hp_free_the_free_list() { while (p) { cur = p; p = p->prev_hprof; - efree(cur); + free(cur); } } @@ -954,7 +961,8 @@ static hp_entry_t *hp_fast_alloc_hprof_entry() { hp_globals.entry_free_list = p->prev_hprof; return p; } else { - return (hp_entry_t *)emalloc(sizeof(hp_entry_t)); + hp_entry_t *tmp = malloc(sizeof(hp_entry_t)); + return tmp; } } @@ -1454,7 +1462,6 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { * @author hzhao, kannan, Jason */ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { - zend_op_array *ops = &execute_data->func->op_array; zend_string *func = NULL; int hp_profile_flag = 1; @@ -1483,7 +1490,8 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { memcpy(func->val + run_init_len, filename->val, filename->len); } - if (!func) { + if (!func || hp_globals.enabled == 0) { + if (func) zend_string_free(func); _zend_execute_ex(execute_data TSRMLS_CC); return; } @@ -1520,7 +1528,9 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re func = current_data->func->op_array.function_name ; if (func && strcmp("xhprof_enable", func->val) != 0) { - BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag); + if (hp_globals.enabled == 1) { + BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag); + } } if (!_zend_execute_internal) { @@ -1626,9 +1636,8 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { break; } BEGIN_PROFILING(&hp_globals.entries, zend_string_init(ROOT_SYMBOL, sizeof(ROOT_SYMBOL) - 1, 1), hp_profile_flag); - /* return here or recu*/ return; - + /* Replace zend_compile_file with our proxy */ _zend_compile_file = zend_compile_file; zend_compile_file = hp_compile_file; @@ -1655,7 +1664,7 @@ static void hp_begin(long level, long xhprof_flags TSRMLS_DC) { hp_init_profiler_state(level TSRMLS_CC); /* start profiling from fictitious main() */ - //BEGIN_PROFILING(&hp_globals.entries, ROOT_SYMBOL, hp_profile_flag); + BEGIN_PROFILING(&hp_globals.entries, zend_string_init(ROOT_SYMBOL, sizeof(ROOT_SYMBOL) - 1, 1), hp_profile_flag); } } @@ -1688,13 +1697,14 @@ static void hp_stop(TSRMLS_D) { while (hp_globals.entries) { END_PROFILING(&hp_globals.entries, hp_profile_flag); } - - zend_execute_ex = _zend_execute_ex; - zend_execute_internal = _zend_execute_internal; - - /* Remove proxies, restore the originals */ - zend_compile_file = _zend_compile_file; - zend_compile_string = _zend_compile_string; + + /* We have done this in RSHUT */ + //zend_execute_ex = _zend_execute_ex; + //zend_execute_internal = _zend_execute_internal; + // + ///* Remove proxies, restore the originals */ + //zend_compile_file = _zend_compile_file; + //zend_compile_string = _zend_compile_string; /* Resore cpu affinity. */ restore_cpu_affinity(&hp_globals.prev_mask); From 6d243fd10e260c60f9d50c1b9a4af2c72e43d77f Mon Sep 17 00:00:00 2001 From: Jason Young Date: Fri, 11 Dec 2015 16:38:18 +0800 Subject: [PATCH 37/45] Added README --- README | 4 +++ examples/sample.php | 11 +++++++++ extension/tests/common.php | 34 -------------------------- extension/tests/xhprof_004_inc.php | 26 -------------------- extension/tests/xhprof_004_require.php | 28 --------------------- extension/tests/xhprof_010_append.php | 3 --- extension/tests/xhprof_011_prepend.php | 4 --- 7 files changed, 15 insertions(+), 95 deletions(-) delete mode 100644 extension/tests/common.php delete mode 100644 extension/tests/xhprof_004_inc.php delete mode 100644 extension/tests/xhprof_004_require.php delete mode 100644 extension/tests/xhprof_010_append.php delete mode 100644 extension/tests/xhprof_011_prepend.php diff --git a/README b/README index a8c15fa9..d710c1b2 100644 --- a/README +++ b/README @@ -1,3 +1,7 @@ +# xhporf for PHP7 + +Please do not use this in an production env. + For installation and usage notes refer to: xhprof_html/docs/index.html diff --git a/examples/sample.php b/examples/sample.php index 1be370d3..d7e280ff 100644 --- a/examples/sample.php +++ b/examples/sample.php @@ -28,6 +28,17 @@ function foo() { // display raw xhprof data for the profiler run print_r($xhprof_data); +xhprof_enable(); + +// run program +for ($i = 0; $i < 1000; $i++) { + + foo(); +} + +// stop profiler +$xhprof_data = xhprof_disable(); +print_r($xhprof_data); $XHPROF_ROOT = realpath(dirname(__FILE__) .'/..'); include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php"; diff --git a/extension/tests/common.php b/extension/tests/common.php deleted file mode 100644 index f808ff38..00000000 --- a/extension/tests/common.php +++ /dev/null @@ -1,34 +0,0 @@ - $metrics) { - echo str_pad($func, 40) . ":"; - ksort($metrics); - foreach ($metrics as $name => $value) { - - // Only call counts are stable. - // Wild card everything else. We still print - // the metric name to ensure it was collected. - if ($name != "ct") { - $value = "*"; - } else { - $value = str_pad($value, 8, " ", STR_PAD_LEFT); - } - - echo " {$name}={$value};"; - } - echo "\n"; - } -} diff --git a/extension/tests/xhprof_004_inc.php b/extension/tests/xhprof_004_inc.php deleted file mode 100644 index 81b8045e..00000000 --- a/extension/tests/xhprof_004_inc.php +++ /dev/null @@ -1,26 +0,0 @@ -" -// which represents the initialization block of a file. -// - -$result1 = explode(" ", "abc def ghi"); - -$result2 = implode(",", $result1); - -echo $result2 . "\n"; - -foo(); - - - - diff --git a/extension/tests/xhprof_004_require.php b/extension/tests/xhprof_004_require.php deleted file mode 100644 index db4352f5..00000000 --- a/extension/tests/xhprof_004_require.php +++ /dev/null @@ -1,28 +0,0 @@ -" -// which represents the initialization block of a file. -// - -$result1 = explode(" ", "abc def ghi"); - -$result2 = implode(",", $result1); - -$result3 = strlen($result2); - -echo $result3 . "\n"; - -bar(); - - - - diff --git a/extension/tests/xhprof_010_append.php b/extension/tests/xhprof_010_append.php deleted file mode 100644 index 7e569914..00000000 --- a/extension/tests/xhprof_010_append.php +++ /dev/null @@ -1,3 +0,0 @@ - Date: Fri, 11 Dec 2015 16:39:25 +0800 Subject: [PATCH 38/45] Rename Readme --- README => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README => README.md (100%) diff --git a/README b/README.md similarity index 100% rename from README rename to README.md From f93671404fd68c9bb0afb88582d1e512ab53f330 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Fri, 11 Dec 2015 16:41:58 +0800 Subject: [PATCH 39/45] Added README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d710c1b2..d24d3e82 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ Please do not use this in an production env. -For installation and usage notes refer to: - xhprof_html/docs/index.html +生产环境勿用。 +代码简直没法看。 -To view the latest version of the doc, go to: - http://pecl.php.net/package/xhprof ---> [View Documentation] From a1ce31560ce3177fccfcb7b0bbd6212aafec9278 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Mon, 11 Jan 2016 10:43:44 +0800 Subject: [PATCH 40/45] Update readme --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index d24d3e82..301b224d 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,20 @@ Please do not use this in an production env. 生产环境勿用。 代码简直没法看。 + +## Install + +### Compile in Linux +``` +$ /$PHP7/bin/phpize +$ ./configure --with-php-config=/$PHP7/bin/php-config +$ make && make install +``` +edit php.ini, add a new line: +``` +extension=xhprof.so +``` +make sure it works: +``` +php7 -m |grep xhprof +``` From f6b73f72f919936c01f08de4f44af04a74fe4ffd Mon Sep 17 00:00:00 2001 From: Jason Young Date: Mon, 28 Mar 2016 18:46:57 +0800 Subject: [PATCH 41/45] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 301b224d..e516ad6f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# xhporf for PHP7 +# xhprof for PHP7 Please do not use this in an production env. From 17a22b2727ed28196b65dcf39d35b95d7d31dee0 Mon Sep 17 00:00:00 2001 From: zhaoxiwu Date: Wed, 19 Oct 2016 19:13:34 +0800 Subject: [PATCH 42/45] fix bug:in the prof result internal method does not display class name --- extension/xhprof.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 1e1da274..90fefcf6 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -1469,8 +1469,8 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { /* check if was in a class */ if (execute_data ->called_scope != NULL && func != NULL) { //this is a class method; - zend_string *class_name = execute_data->called_scope ->name; - zend_string *func_name = func; + zend_string *class_name = execute_data->called_scope->name; + zend_string *func_name = func; int class_name_len = class_name->len; func = zend_string_init(class_name->val, class_name_len + 2 + func_name->len, 0); @@ -1478,7 +1478,7 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { memcpy(func->val + class_name_len + 2, func_name->val, func_name->len); } else if (func) { //just do the copy; - func = zend_string_init(func->val, func->len, 0); + func = zend_string_init(func->val, func->len, 0); } else if (execute_data->literals->u1.type_info == 4) { //could include, not sure others has the same value @@ -1527,6 +1527,20 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re current_data = EG(current_execute_data); func = current_data->func->op_array.function_name ; + //check is a class method + if(current_data->func->op_array.scope != NULL) { + zend_string *class_name = current_data->func->op_array.scope->name; + zend_string *func_name = func; + + int class_name_len = class_name->len; + func = zend_string_init(class_name->val, class_name_len + 2 + func_name->len, 0); + memcpy(func->val + class_name_len, "::", 2); + memcpy(func->val + class_name_len + 2, func_name->val, func_name->len); + } else { + //just do the copy; + func = zend_string_init(func->val, func->len, 0); + } + if (func && strcmp("xhprof_enable", func->val) != 0) { if (hp_globals.enabled == 1) { BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag); @@ -1551,6 +1565,10 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re //zend_string_free(func); } + if (func) { + zend_string_free(func); + } + } /** From 31983d8862c7d219e3b434e22388b5db7e5fcbdf Mon Sep 17 00:00:00 2001 From: Yo-An Lin Date: Tue, 17 Jan 2017 22:27:55 +0800 Subject: [PATCH 43/45] Update xhprof.c --- extension/xhprof.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 90fefcf6..72c27622 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -1464,12 +1464,15 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries TSRMLS_DC) { ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data TSRMLS_DC) { zend_string *func = NULL; int hp_profile_flag = 1; + + zend_class_entry *called_scope; + called_scope = zend_get_called_scope(execute_data); func = execute_data->func->internal_function.function_name; /* check if was in a class */ - if (execute_data ->called_scope != NULL && func != NULL) { + if (called_scope != NULL && func != NULL) { //this is a class method; - zend_string *class_name = execute_data->called_scope->name; + zend_string *class_name = called_scope->name; zend_string *func_name = func; int class_name_len = class_name->len; From 10eac34cf9be2b29864120f9a9f771a96a1368e4 Mon Sep 17 00:00:00 2001 From: Provoker Date: Wed, 1 Mar 2017 14:12:08 +0500 Subject: [PATCH 44/45] Fix segfault --- extension/xhprof.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/xhprof.c b/extension/xhprof.c index 72c27622..3c83d4ba 100644 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -1539,7 +1539,7 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re func = zend_string_init(class_name->val, class_name_len + 2 + func_name->len, 0); memcpy(func->val + class_name_len, "::", 2); memcpy(func->val + class_name_len + 2, func_name->val, func_name->len); - } else { + } else if (func) { //just do the copy; func = zend_string_init(func->val, func->len, 0); } From 73c34e0872e242a2760e8043a5393921f39e1e84 Mon Sep 17 00:00:00 2001 From: Jason Young <4018764+rustjason@users.noreply.github.com> Date: Sun, 25 Nov 2018 12:51:53 +0800 Subject: [PATCH 45/45] Update README.md --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index e516ad6f..3bd574ab 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,6 @@ Please do not use this in an production env. -生产环境勿用。 -代码简直没法看。 - ## Install