From fefcc60b0d881ad8313993574b7ea0e417db898a Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Mon, 14 Nov 2016 06:30:19 -0800 Subject: [PATCH 1/3] Use `--hook[=]` to profile all hooks, or callbacks to spec hook --- features/profile-eval-file.feature | 19 +++++++ features/profile-eval.feature | 13 +++++ inc/class-command.php | 79 +++++++++++++++++------------- inc/class-profiler.php | 5 ++ 4 files changed, 83 insertions(+), 33 deletions(-) diff --git a/features/profile-eval-file.feature b/features/profile-eval-file.feature index 0d6dd1f..5f51d32 100644 --- a/features/profile-eval-file.feature +++ b/features/profile-eval-file.feature @@ -53,3 +53,22 @@ Feature: Profile arbitary file execution Then STDOUT should be a table containing rows: | cache_hits | cache_misses | | 2 | 0 | + + Scenario: Profile a function calling a hook + Given a WP install + And a calls-hook.php file: + """ + * : The code to execute, as a string. * + * [--hook[=]] + * : Focus on key metrics for all hooks, or callbacks on a specific hook. + * * [--fields=] * : Display one or more fields. * @@ -235,31 +238,13 @@ class Command { * - csv * --- * - * @when before_wp_load * @subcommand eval */ public function eval_( $args, $assoc_args ) { - - $profiler = new Profiler( false, false ); - $profiler->run(); - - $logger = new Logger(); - $logger->start(); - eval( $args[0] ); - $logger->stop(); - - $fields = array( - 'time', - 'query_time', - 'query_count', - 'cache_ratio', - 'cache_hits', - 'cache_misses', - 'request_time', - 'request_count', - ); - $formatter = new Formatter( $assoc_args, $fields ); - $formatter->display_items( array( $logger ), false ); + $statement = $args[0]; + self::profile_eval_ish( $assoc_args, function() use ( $statement ) { + eval( $statement ); + }); } /** @@ -274,6 +259,9 @@ class Command { * * : The path to the PHP file to execute and profile. * + * [--hook[=]] + * : Focus on key metrics for all hooks, or callbacks on a specific hook. + * * [--fields=] * : Display one or more fields. * @@ -288,7 +276,6 @@ class Command { * - csv * --- * - * @when before_wp_load * @subcommand eval-file */ public function eval_file( $args, $assoc_args ) { @@ -298,15 +285,41 @@ class Command { WP_CLI::error( "'$file' does not exist." ); } - $profiler = new Profiler( false, false ); + self::profile_eval_ish( $assoc_args, function() use ( $file ) { + self::include_file( $file ); + }); + } + + /** + * Profile an eval or eval-file statement. + */ + private static function profile_eval_ish( $assoc_args, $profile_callback ) { + $hook = Utils\get_flag_value( $assoc_args, 'hook' ); + $type = $focus = false; + $fields = array(); + if ( $hook ) { + $type = 'hook'; + if ( true !== $hook ) { + $focus = $hook; + $fields[] = 'callback'; + $fields[] = 'location'; + } else { + $fields[] = 'hook'; + } + } + $profiler = new Profiler( $type, $focus ); $profiler->run(); - - $logger = new Logger(); - $logger->start(); - self::include_file( $file ); - $logger->stop(); - - $fields = array( + if ( $hook ) { + $profile_callback(); + $loggers = $profiler->get_loggers(); + } else { + $logger = new Logger(); + $logger->start(); + $profile_callback(); + $logger->stop(); + $loggers = array( $logger ); + } + $fields = array_merge( $fields, array( 'time', 'query_time', 'query_count', @@ -315,9 +328,9 @@ class Command { 'cache_misses', 'request_time', 'request_count', - ); + ) ); $formatter = new Formatter( $assoc_args, $fields ); - $formatter->display_items( array( $logger ), false ); + $formatter->display_items( $loggers, false ); } /** diff --git a/inc/class-profiler.php b/inc/class-profiler.php index 78f10bf..a496573 100644 --- a/inc/class-profiler.php +++ b/inc/class-profiler.php @@ -370,6 +370,11 @@ class Profiler { */ private function load_wordpress_with_template() { + // WordPress already ran once. + if ( function_exists( 'add_filter' ) ) { + return; + } + if ( 'stage' === $this->type && true === $this->focus ) { $hooks = array(); foreach( $this->stage_hooks as $stage_hook ) { From bb5a2ac97bbb24b3a9db11e3fc964532e93086b7 Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Mon, 14 Nov 2016 06:31:51 -0800 Subject: [PATCH 2/3] Regenerate README based on new argument --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e032f88..4cc003d 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ will need to execute during the course of the request. Profile arbitrary code execution. ~~~ -wp profile eval [--fields=] [--format=] +wp profile eval [--hook[=]] [--fields=] [--format=] ~~~ Code execution happens after WordPress has loaded entirely, which means @@ -156,6 +156,9 @@ current theme. The code to execute, as a string. + [--hook[=]] + Focus on key metrics for all hooks, or callbacks on a specific hook. + [--fields=] Display one or more fields. @@ -177,7 +180,7 @@ current theme. Profile execution of an arbitrary file. ~~~ -wp profile eval-file [--fields=] [--format=] +wp profile eval-file [--hook[=]] [--fields=] [--format=] ~~~ File execution happens after WordPress has loaded entirely, which means @@ -189,6 +192,9 @@ current theme. The path to the PHP file to execute and profile. + [--hook[=]] + Focus on key metrics for all hooks, or callbacks on a specific hook. + [--fields=] Display one or more fields. From b35ee4e6e6e028d1d04705a5961803f48630570e Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Mon, 14 Nov 2016 06:41:41 -0800 Subject: [PATCH 3/3] Update test that fails every time I add a new feature --- features/profile.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/profile.feature b/features/profile.feature index 9cda037..29544e9 100644 --- a/features/profile.feature +++ b/features/profile.feature @@ -6,8 +6,8 @@ Feature: Basic profile usage When I run `wp profile` Then STDOUT should be: """ - usage: wp profile eval [--fields=] [--format=] - or: wp profile eval-file [--fields=] [--format=] + usage: wp profile eval [--hook[=]] [--fields=] [--format=] + or: wp profile eval-file [--hook[=]] [--fields=] [--format=] or: wp profile hook [] [--all] [--spotlight] [--url=] [--fields=] [--format=] or: wp profile stage [] [--all] [--spotlight] [--url=] [--fields=] [--format=]