diff options
author | mattab <matthieu.aubry@gmail.com> | 2013-11-18 01:39:43 +0400 |
---|---|---|
committer | mattab <matthieu.aubry@gmail.com> | 2013-11-18 01:39:43 +0400 |
commit | 681a5c8c80cc538d29e7e587a32abc9e6c7d8181 (patch) | |
tree | b4b4b529f476de139cb019b7fcf02c5a41bc359f | |
parent | 070035fe4fd0c370445f5c56919aff180935cd28 (diff) |
Improving XHProf support. At the end of a request with XHProf enabled, it will output the link to see the profiling info. New --xhprof option to archive.php, and enabling XHProf when &xhprof=1 is found in the request.
-rw-r--r-- | core/FrontController.php | 5 | ||||
-rw-r--r-- | core/Profiler.php | 94 | ||||
-rw-r--r-- | misc/cron/archive.php | 15 | ||||
-rw-r--r-- | tests/PHPUnit/proxy/archive.php | 2 | ||||
-rw-r--r-- | tests/PHPUnit/proxy/index.php | 3 | ||||
-rw-r--r-- | tests/README.xhprof.md | 6 |
6 files changed, 122 insertions, 3 deletions
diff --git a/core/FrontController.php b/core/FrontController.php index a1790cf624..e86aceff78 100644 --- a/core/FrontController.php +++ b/core/FrontController.php @@ -271,9 +271,14 @@ class FrontController extends Singleton ); libxml_disable_entity_loader(); // prevent remote file inclusion + Filechecks::dieIfDirectoriesNotWritable($directoriesToCheck); self::assignCliParametersToRequest(); + if(!empty($_GET['xhprof'])) { + Profiler::setupProfilerXHProf($mainRun = false); + } + Translate::loadEnglishTranslation(); $exceptionToThrow = self::createConfigObject(); diff --git a/core/Profiler.php b/core/Profiler.php index bce7da3d33..7a0f2b0d39 100644 --- a/core/Profiler.php +++ b/core/Profiler.php @@ -182,4 +182,98 @@ class Profiler } Log::debug($output); } + + /** + * Initializes Profiling via XHProf. + * See: https://github.com/piwik/piwik/blob/master/tests/README.xhprof.md + */ + public static function setupProfilerXHProf($mainRun = false) + { + if(!empty($GLOBALS['PIWIK_TRACKER_MODE'])) { + // do not profile Tracker + return; + } + + $path = PIWIK_INCLUDE_PATH . '/tests/lib/xhprof-0.9.4/xhprof_lib/utils/xhprof_runs.php'; + if(!file_exists($path)) { + return; + } + + require_once $path; + + $currentGitBranch = self::getCurrentGitBranch(); + $profilerNamespace = "piwik"; + if($currentGitBranch != 'master') { + $profilerNamespace .= "." . $currentGitBranch; + } + + xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY); + + if($mainRun) { + self::setProfilingRunIds(array()); + } + + register_shutdown_function(function () use($profilerNamespace, $mainRun) { + $xhprofData = xhprof_disable(); + $xhprofRuns = new \XHProfRuns_Default(); + $runId = $xhprofRuns->save_run($xhprofData, $profilerNamespace); + + $runs = self::getProfilingRunIds(); + $runs[] = $runId; +// $weights = array_fill(0, count($runs), 1); +// $aggregate = xhprof_aggregate_runs($xhprofRuns, $runs, $weights, $profilerNamespace); +// $runId = $xhprofRuns->save_run($aggregate, $profilerNamespace); + + if($mainRun) { + $runIds = implode(',', $runs); + $out = "\n\nHere is the profiler URL aggregating all runs triggered from this process: "; + $baseUrl = "http://" . $_SERVER['HTTP_HOST'] . "/" . $_SERVER['REQUEST_URI']; + $baseUrlStored = SettingsPiwik::getPiwikUrl(); + if(strlen($baseUrlStored) > strlen($baseUrl)) { + $baseUrl = $baseUrlStored; + } + $baseUrl = "\n\n" . $baseUrl + ."tests/lib/xhprof-0.9.4/xhprof_html/?source=$profilerNamespace&run="; + $out .= $baseUrl . "$runIds\n\n"; + $out .= "Main run profile:"; + $out .= $baseUrl . "$runId\n\n"; + Log::info($out); + } else { + self::setProfilingRunIds($runs); + } + }); + } + + private static function setProfilingRunIds($ids) + { + file_put_contents( self::getPathToXHProfRunIds(), json_encode($ids) ); + chmod(self::getPathToXHProfRunIds(), 0777); + } + + private static function getProfilingRunIds() + { + $runIds = file_get_contents( self::getPathToXHProfRunIds() ); + $array = json_decode($runIds, $assoc = true); + if(!is_array($array)) { + $array = array(); + } + return $array; + } + + private static function getCurrentGitBranch() + { + $firstLineOfGitHead = file(PIWIK_INCLUDE_PATH . '/.git/HEAD'); + $firstLineOfGitHead = $firstLineOfGitHead[0]; + $parts = explode("/", $firstLineOfGitHead); + $currentGitBranch = trim($parts[2]); + return $currentGitBranch; + } + + /** + * @return string + */ + private static function getPathToXHProfRunIds() + { + return PIWIK_INCLUDE_PATH . '/tmp/cache/tests-xhprof-runs'; + } }
\ No newline at end of file diff --git a/misc/cron/archive.php b/misc/cron/archive.php index c796e3c018..dbc947eb4b 100644 --- a/misc/cron/archive.php +++ b/misc/cron/archive.php @@ -44,6 +44,8 @@ Arguments: If not specified, defaults to ". CronArchive::SECONDS_DELAY_BETWEEN_PERIOD_ARCHIVES.". --force-idsites=1,2,n Restricts archiving to the specified website IDs, comma separated list. + --xhprof + Enables XHProf profiler for this archive.php run. Requires XHPRof (see tests/README.xhprof.md). --accept-invalid-ssl-certificate It is _NOT_ recommended to use this argument. Instead, you should use a valid SSL certificate! It can be useful if you specified --url=https://... or if you are using Piwik with force_ssl=1 @@ -138,6 +140,7 @@ class CronArchive private $output = ''; private $archiveAndRespectTTL = true; private $shouldArchiveAllSites = false; + private $shouldStartProfiler = false; private $acceptInvalidSSLCertificate = false; private $lastSuccessRunTimestamp = false; private $errors = array(); @@ -173,6 +176,10 @@ class CronArchive $this->segments = $this->initSegmentsToArchive(); $this->allWebsites = APISitesManager::getInstance()->getAllSitesId(); $this->websites = $this->initWebsitesToProcess(); + if($this->shouldStartProfiler) { + \Piwik\Profiler::setupProfilerXHProf($mainRun = true); + $this->log("XHProf profiling is enabled."); + } } /** @@ -543,7 +550,7 @@ class CronArchive if (!empty($aCurl)) { $running = null; do { - usleep(10000); + usleep(1000); curl_multi_exec($mh, $running); } while ($running > 0); @@ -623,6 +630,11 @@ class CronArchive private function request($url) { $url = $this->piwikUrl . $url . self::APPEND_TO_API_REQUEST; + + if($this->shouldStartProfiler) { + $url .= "&xhprof=1"; + } + //$this->log($url); try { $response = Http::sendHttpRequestBy('curl', $url, $timeout = 300, $userAgent = null, $destinationPath = null, $file = null, $followDepth = 0, $acceptLanguage = false, $acceptInvalidSSLCertificate = $this->acceptInvalidSSLCertificate); @@ -746,6 +758,7 @@ class CronArchive $this->acceptInvalidSSLCertificate = $this->isParameterSet("accept-invalid-ssl-certificate"); $this->processPeriodsMaximumEverySeconds = $this->getDelayBetweenPeriodsArchives(); $this->shouldArchiveAllSites = (bool) $this->isParameterSet("force-all-websites"); + $this->shouldStartProfiler = (bool) $this->isParameterSet("xhprof"); $restrictToIdSites = $this->isParameterSet("force-idsites", true); $this->shouldArchiveSpecifiedSites = \Piwik\Site::getIdSitesFromIdSitesString($restrictToIdSites); $this->lastSuccessRunTimestamp = Option::get(self::OPTION_ARCHIVING_FINISHED_TS); diff --git a/tests/PHPUnit/proxy/archive.php b/tests/PHPUnit/proxy/archive.php index 75fcbcd4b8..02ef4c611a 100644 --- a/tests/PHPUnit/proxy/archive.php +++ b/tests/PHPUnit/proxy/archive.php @@ -4,6 +4,8 @@ define('PIWIK_ARCHIVE_NO_TRUNCATE', true); require realpath(dirname(__FILE__)) . "/includes.php"; +\Piwik\Profiler::setupProfilerXHProf(); + Piwik_TestingEnvironment::addHooks(); // include archive.php, and let 'er rip diff --git a/tests/PHPUnit/proxy/index.php b/tests/PHPUnit/proxy/index.php index c0c0c6166d..33620266e5 100644 --- a/tests/PHPUnit/proxy/index.php +++ b/tests/PHPUnit/proxy/index.php @@ -17,6 +17,9 @@ Piwik_TestingEnvironment::addHooks(); \Piwik\Tracker::setTestEnvironment(); Cache::deleteTrackerCache(); +\Piwik\Profiler::setupProfilerXHProf(); + + // Disable index.php dispatch since we do it manually below define('PIWIK_ENABLE_DISPATCH', false); include PIWIK_INCLUDE_PATH . '/index.php'; diff --git a/tests/README.xhprof.md b/tests/README.xhprof.md index 000d60ad0a..1f648ad3f3 100644 --- a/tests/README.xhprof.md +++ b/tests/README.xhprof.md @@ -9,7 +9,9 @@ First, XHProf must be built (this guide assumes you're using a linux variant): * Navigate to the XHProf extension directory. - $ cd /path/to/piwik/tests/lib/xhprof-0.9.2/extension + $ cd /path/to/piwik/tests/lib/ + $ wget http://pecl.php.net/get/xhprof + $ tar -xzvf xhprof * Build XHProf. @@ -23,7 +25,7 @@ First, XHProf must be built (this guide assumes you're using a linux variant): ``` [xhprof] - extension=/path/to/piwik/tests/lib/xhprof-0.9.2/extension/modules/xhprof.so + extension=/path/to/piwik/tests/lib/xhprof-0.9.4/extension/modules/xhprof.so xhprof.output_dir=/path/to/output/dir ``` |