Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordiosmosis <benakamoorthi@fastmail.fm>2014-08-20 23:05:32 +0400
committerdiosmosis <benakamoorthi@fastmail.fm>2014-08-21 18:49:19 +0400
commit2a3fa03749e74847a243df4a780f9062e0945d3c (patch)
tree6be466b9347da91a15989f30d94f3b7915553815 /core/Profiler.php
parent42f5b0273649978540a331786a42937d92fdd8c3 (diff)
Get xhprof integration to work. Only setup xhprof once per php execution and correctly aggregate xhprof runs (xhprof aggregation will always normalize so we must aggregate ourselves).
Diffstat (limited to 'core/Profiler.php')
-rw-r--r--core/Profiler.php100
1 files changed, 78 insertions, 22 deletions
diff --git a/core/Profiler.php b/core/Profiler.php
index 04d2443082..2000701bff 100644
--- a/core/Profiler.php
+++ b/core/Profiler.php
@@ -9,6 +9,7 @@
namespace Piwik;
use Exception;
+use XHProfRuns_Default;
/**
* Class Profiler helps with measuring memory, and profiling the database.
@@ -24,6 +25,13 @@ use Exception;
class Profiler
{
/**
+ * Whether xhprof has been setup or not.
+ *
+ * @var bool
+ */
+ private static $isXhprofSetup = false;
+
+ /**
* Returns memory usage
*
* @return string
@@ -197,11 +205,24 @@ class Profiler
return;
}
+ if (self::$isXhprofSetup) {
+ return;
+ }
+
+ $xhProfPath = PIWIK_INCLUDE_PATH . '/vendor/facebook/xhprof/extension/modules/xhprof.so';
+ if (!file_exists($xhProfPath)) {
+ throw new Exception("Cannot find xhprof, run 'composer update' and build the extension."); // TODO: automate building w/ composer
+ }
+
if (!function_exists('xhprof_enable')) {
- throw new Exception("Cannot find xhprof, run 'composer update'.");
+ throw new Exception("Cannot find xhprof_enable, make sure to add 'extension=$xhProfPath' to your php.ini.");
}
- if (!is_writable(ini_get("xhprof.output_dir"))) {
+ $outputDir = ini_get("xhprof.output_dir");
+ if (empty($outputDir)) {
+ throw new Exception("The profiler output dir is not set. Add 'xhprof.output_dir=...' to your php.ini.");
+ }
+ if (!is_writable($outputDir)) {
throw new Exception("The profiler output dir '" . ini_get("xhprof.output_dir") . "' should exist and be writable.");
}
@@ -223,40 +244,75 @@ class Profiler
self::setProfilingRunIds(array());
}
- register_shutdown_function(function () use($profilerNamespace, $mainRun) {
+ $baseUrlStored = SettingsPiwik::getPiwikUrl();
+
+ register_shutdown_function(function () use($profilerNamespace, $mainRun, $baseUrlStored) {
$xhprofData = xhprof_disable();
- $xhprofRuns = new \XHProfRuns_Default();
+ $xhprofRuns = new XHProfRuns_Default();
$runId = $xhprofRuns->save_run($xhprofData, $profilerNamespace);
- if(empty($runId)) {
+ if (empty($runId)) {
die('could not write profiler run');
}
- $runs = self::getProfilingRunIds();
- $runs[] = $runId;
- if($mainRun) {
- $runIds = implode(',', $runs);
+ $runs = Profiler::getProfilingRunIds();
+ array_unshift($runs, $runId);
+
+ if ($mainRun) {
+ self::aggregateXhprofRuns($runs, $profilerNamespace, $saveTo = $runId);
+
$out = "\n\n";
$baseUrl = "http://" . @$_SERVER['HTTP_HOST'] . "/" . @$_SERVER['REQUEST_URI'];
- $baseUrlStored = SettingsPiwik::getPiwikUrl();
- if(strlen($baseUrlStored) > strlen($baseUrl)) {
+ if (strlen($baseUrlStored) > strlen($baseUrl)) {
$baseUrl = $baseUrlStored;
}
- $baseUrl = "\n" . $baseUrl
- ."tests/lib/xhprof-0.9.4/xhprof_html/?source=$profilerNamespace&run=";
-
- $out .= "Profiler report is available at:";
- $out .= $baseUrl . $runId;
- if($runId != $runIds) {
- $out .= "\n\nProfiler Report aggregating all runs triggered from this process: ";
- $out .= $baseUrl . $runIds;
- }
+ $baseUrl = $baseUrlStored . "vendor/facebook/xhprof/xhprof_html/?source=$profilerNamespace&run=$runId";
+
+ $out .= "Profiler report is available at:\n";
+ $out .= $baseUrl;
$out .= "\n\n";
- echo ($out);
+
+ echo $out;
} else {
- self::setProfilingRunIds($runs);
+ Profiler::setProfilingRunIds($runs);
}
});
+
+ self::$isXhprofSetup = true;
+ }
+
+ /**
+ * Aggregates xhprof runs w/o normalizing (xhprof_aggregate_runs will always average data which
+ * does not fit Piwik's use case).
+ */
+ private static function aggregateXhprofRuns($runIds, $profilerNamespace, $saveToRunId)
+ {
+ $xhprofRuns = new XHProfRuns_Default();
+
+ $aggregatedData = array();
+
+ foreach ($runIds as $runId) {
+ $xhprofRunData = $xhprofRuns->get_run($runId, $profilerNamespace, $description);
+
+ foreach ($xhprofRunData as $key => $data) {
+ if (empty($aggregatedData[$key])) {
+ $aggregatedData[$key] = $data;
+ } else {
+ // don't aggregate main() metrics since only the super run has the correct metrics for the entire run
+ if ($key == "main()") {
+ continue;
+ }
+
+ $aggregatedData[$key]["ct"] += $data["ct"];
+ $aggregatedData[$key]["wt"] += $data["wt"];
+ $aggregatedData[$key]["cpu"] += $data["cpu"];
+ $aggregatedData[$key]["mu"] += $data["mu"];
+ $aggregatedData[$key]["pmu"] = max($aggregatedData[$key]["pmu"], $data["pmu"]);
+ }
+ }
+ }
+
+ $xhprofRuns->save_run($aggregatedData, $profilerNamespace, $saveToRunId);
}
private static function setProfilingRunIds($ids)