From 8f7dcb34534faea18b2f180df3e8c2e635563699 Mon Sep 17 00:00:00 2001 From: Russell Smith Date: Tue, 9 Aug 2016 10:09:23 +1000 Subject: [PATCH] MDL-55504 profiling: Support for PHPUnit and big profiles. To support PHPUnit we need to support large profiles, these may include backups and restores. To do that the following was required; - gzcompress for database space saving. - gzcompress for XML DomDocument field to say < 10Mb and allow imports. - Save PHPUnit runs directly to a file so they can be imported to the normal database. - Memory allowance on profiling view pages increases to support large profiles. --- config-dist.php | 1 + lib/phpunit/bootstrap.php | 4 ++++ lib/xhprof/xhprof_html/callgraph.php | 1 + lib/xhprof/xhprof_html/index.php | 1 + lib/xhprof/xhprof_moodle.php | 30 +++++++++++++++++++++++++--- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/config-dist.php b/config-dist.php index ac9297e799fe6..c835d9809a116 100644 --- a/config-dist.php +++ b/config-dist.php @@ -648,6 +648,7 @@ // $CFG->phpunit_prefix = 'phpu_'; // $CFG->phpunit_dataroot = '/home/example/phpu_moodledata'; // $CFG->phpunit_directorypermissions = 02777; // optional +// $CFG->phpunit_profilingenabled = true; // optional to profile PHPUnit runs. // // //========================================================================= diff --git a/lib/phpunit/bootstrap.php b/lib/phpunit/bootstrap.php index aff8506868eef..4927cc615f18a 100644 --- a/lib/phpunit/bootstrap.php +++ b/lib/phpunit/bootstrap.php @@ -219,6 +219,10 @@ // finish moodle init define('ABORT_AFTER_CONFIG_CANCEL', true); +if (isset($CFG->phpunit_profilingenabled) && $CFG->phpunit_profilingenabled) { + $CFG->profilingenabled = true; + $CFG->profilingincluded = '*'; +} require("$CFG->dirroot/lib/setup.php"); raise_memory_limit(MEMORY_HUGE); diff --git a/lib/xhprof/xhprof_html/callgraph.php b/lib/xhprof/xhprof_html/callgraph.php index 308c8bce95c26..49cd8efc4a7ca 100644 --- a/lib/xhprof/xhprof_html/callgraph.php +++ b/lib/xhprof/xhprof_html/callgraph.php @@ -34,6 +34,7 @@ require_once($CFG->libdir . '/xhprof/xhprof_moodle.php'); require_login(); require_capability('moodle/site:config', context_system::instance()); +raise_memory_limit(MEMORY_HUGE); \core\session\manager::write_close(); // End moodle modification. diff --git a/lib/xhprof/xhprof_html/index.php b/lib/xhprof/xhprof_html/index.php index 75bef73a478b0..80e7821fe92b3 100644 --- a/lib/xhprof/xhprof_html/index.php +++ b/lib/xhprof/xhprof_html/index.php @@ -36,6 +36,7 @@ require_once($CFG->libdir . '/xhprof/xhprof_moodle.php'); require_login(); require_capability('moodle/site:config', context_system::instance()); +raise_memory_limit(MEMORY_HUGE); \core\session\manager::write_close(); // End moodle modification. diff --git a/lib/xhprof/xhprof_moodle.php b/lib/xhprof/xhprof_moodle.php index fb0794a719ff1..293ffacaad1e2 100644 --- a/lib/xhprof/xhprof_moodle.php +++ b/lib/xhprof/xhprof_moodle.php @@ -29,6 +29,7 @@ // Need some stuff from moodle. require_once($CFG->libdir . '/tablelib.php'); require_once($CFG->libdir . '/setuplib.php'); +require_once($CFG->libdir . '/filelib.php'); require_once($CFG->libdir . '/phpunit/classes/util.php'); require_once($CFG->dirroot . '/backup/util/xml/xml_writer.class.php'); require_once($CFG->dirroot . '/backup/util/xml/output/xml_output.class.php'); @@ -586,6 +587,9 @@ function profiling_import_runs($file, $commentprefix = '') { $runarr['data'] = clean_param($rdom->getElementsByTagName('data')->item(0)->nodeValue, PARAM_CLEAN); // If the runid does not exist, insert it. if (!$DB->record_exists('profiling', array('runid' => $runarr['runid']))) { + if (@gzuncompress(base64_decode($runarr['data'])) === false) { + $runarr['data'] = base64_encode(gzcompress(base64_decode($runarr['data']))); + } $DB->insert_record('profiling', $runarr); } else { return false; @@ -818,7 +822,12 @@ public function get_run($run_id, $type, &$run_desc) { $run_desc = $this->url . ($rec->runreference ? ' (R) ' : ' ') . ' - ' . s($rec->runcomment); - return unserialize(base64_decode($rec->data)); + // Handle historical runs that aren't compressed. + if (@gzuncompress(base64_decode($rec->data)) === false) { + return unserialize(base64_decode($rec->data)); + } else { + return unserialize(gzuncompress(base64_decode($rec->data))); + } } /** @@ -828,7 +837,7 @@ public function get_run($run_id, $type, &$run_desc) { * Note that $type is completely ignored */ public function save_run($xhprof_data, $type, $run_id = null) { - global $DB; + global $DB, $CFG; if (is_null($this->url)) { xhprof_error("Warning: You must use the prepare_run() method before saving it"); @@ -847,7 +856,7 @@ public function save_run($xhprof_data, $type, $run_id = null) { $rec = new stdClass(); $rec->runid = $this->runid; $rec->url = $this->url; - $rec->data = base64_encode(serialize($xhprof_data)); + $rec->data = base64_encode(gzcompress(serialize($xhprof_data), 9)); $rec->totalexecutiontime = $this->totalexecutiontime; $rec->totalcputime = $this->totalcputime; $rec->totalcalls = $this->totalcalls; @@ -855,6 +864,21 @@ public function save_run($xhprof_data, $type, $run_id = null) { $rec->timecreated = $this->timecreated; $DB->insert_record('profiling', $rec); + + if (PHPUNIT_TEST) { + // Calculate export variables. + $tempdir = 'profiling'; + make_temp_directory($tempdir); + $runids = array($this->runid); + $filename = $this->runid . '.mpr'; + $filepath = $CFG->tempdir . '/' . $tempdir . '/' . $filename; + + // Generate the mpr file and send it. + if (profiling_export_runs($runids, $filepath)) { + fprintf(STDERR, "Profiling data saved to: ".$filepath."\n"); + } + } + return $this->runid; }