Commit 6af80cae authored by Eloy Lafuente's avatar Eloy Lafuente
Browse files

MDL-24600 profiling - add xhprof integration

parent 88e5c586
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package core
* @subpackage profiling
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// TODO: Move all the DB stuff to profiling_db_xxxx() function in xhprof_moodle.php
require_once(dirname(__FILE__).'/../../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir . '/xhprof/xhprof_moodle.php');
define('PROFILING_RUNSPERPAGE', 50);
// page parameters
$script = optional_param('script', null, PARAM_PATH);
$runid = optional_param('runid', null, PARAM_ALPHANUM);
$runid2 = optional_param('runid2', null, PARAM_ALPHANUM);
$listurl = optional_param('listurl', null, PARAM_PATH);
$runreference= optional_param('runreference', 0, PARAM_INT);
$runcomment = optional_param('runcomment', null, PARAM_TEXT);
$dbfields = 'runid, url, totalexecutiontime, totalcputime, ' .
'totalcalls, totalmemory, runreference, runcomment, timecreated';
admin_externalpage_setup('reportprofiling');
// Always add listurl if available
if ($listurl) {
$listurlnav = new moodle_url('/admin/report/profiling/index.php', array('listurl' => $listurl));
$PAGE->navbar->add($listurl, $listurlnav);
}
// Header
echo $OUTPUT->header();
// We have requested the last available run for one script
if (isset($script)) {
// Get the last available run for the given script
$run = $DB->get_record_sql("SELECT $dbfields
FROM {profiling}
WHERE url = ?
AND id = (SELECT MAX(id)
FROM {profiling}
WHERE url = ?)",
array($script, $script), IGNORE_MISSING);
// No run found for script, warn and exit
if (!$run) {
notice(get_string('cannotfindanyrunforurl', 'report_profiling', $script), 'index.php');
}
// Check if there is any previous run marked as reference one
$prevreferences = $DB->get_records_select('profiling',
'url = ? AND runreference = 1 AND timecreated < ?',
array($run->url, $run->timecreated),
'timecreated DESC', 'runid', 0, 1);
$prevrunid = $prevreferences ? reset($prevreferences)->runid : false;
echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter');
$header = get_string('lastrunof', 'report_profiling', $script);
echo $OUTPUT->heading($header);
$table = profiling_print_run($run, $prevrunid);
echo $table;
echo $OUTPUT->box_end();
// We have requested the diff between 2 runs
} else if (isset($runid) && isset($runid2)) {
$run1 = $DB->get_record('profiling', array('runid'=>$runid), $dbfields, MUST_EXIST);
$run2 = $DB->get_record('profiling', array('runid'=>$runid2), $dbfields, MUST_EXIST);
if ($run1->url == $run2->url && $run1->runid != $run2->runid) {
if ($run2->timecreated < $run1->timecreated) {
$runtemp = $run1;
$run1 = $run2;
$run2 = $runtemp;
}
echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter');
$header = get_string('differencesbetween2runsof', 'report_profiling', $run1->url);
echo $OUTPUT->heading($header);
$table = profiling_print_rundiff($run1, $run2);
echo $table;
echo $OUTPUT->box_end();
}
// We have requested one run, invoke it
} else if (isset($runid)) {
// Check if we are trying to update the runreference/runcomment for the run
if (isset($runcomment) && confirm_sesskey()) {
$id = $DB->get_field('profiling', 'id', array('runid' => $runid), MUST_EXIST);
$rec = new stdClass();
$rec->id = $id;
$rec->runreference = (bool)$runreference;
$rec->runcomment = $runcomment;
$DB->update_record('profiling', $rec);
}
// Get the requested runid
$run = $DB->get_record('profiling', array('runid'=>$runid), $dbfields, IGNORE_MISSING);
// No run found for runid, warn and exit
if (!$run) {
notice(get_string('cannotfindanyrunforrunid', 'report_profiling', $runid), 'index.php');
}
// Check if there is any previous run marked as reference one
$prevreferences = $DB->get_records_select('profiling',
'url = ? AND runreference = 1 AND timecreated < ?',
array($run->url, $run->timecreated),
'timecreated DESC', 'runid', 0, 1);
$prevrunid = $prevreferences ? reset($prevreferences)->runid : false;
echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter');
$header = get_string('summaryof', 'report_profiling', $run->url);
echo $OUTPUT->heading($header);
$table = profiling_print_run($run, $prevrunid);
echo $table;
echo $OUTPUT->box_end();
// Default: List one page of runs
} else {
// The flexitable that will root listings
$table = new xhprof_table_sql('profiling-list-table');
$baseurl = $CFG->wwwroot . '/admin/report/profiling/index.php';
// Check if we are listing all or some URL ones
$sqlconditions = '';
$sqlparams = array();
if (!isset($listurl)) {
$header = get_string('pluginname', 'report_profiling');
$sqlconditions = '1 = 1';
$table->set_listurlmode(false);
} else {
$header = get_string('profilingrunsfor', 'report_profiling', $listurl);
$sqlconditions = 'url = :url';
$sqlparams['url'] = $listurl;
$table->set_listurlmode(true);
$baseurl .= '?listurl=' . urlencode($listurl);
}
echo $OUTPUT->heading($header);
// TODO: Fix flexitable to validate tsort/thide/tshow/tifirs/tilast/page
// TODO: Fix table_sql to allow it to work without WHERE clause
// add silly condition (1 = 1) because of table_sql bug
$table->set_sql($dbfields, '{profiling}', $sqlconditions, $sqlparams);
$table->set_count_sql("SELECT COUNT(*) FROM {profiling} WHERE $sqlconditions", $sqlparams);
$columns = array(
'url', 'timecreated', 'totalexecutiontime', 'totalcputime',
'totalcalls', 'totalmemory', 'runcomment');
$headers = array(
get_string('url'), get_string('date'), get_string('executiontime', 'report_profiling'),
get_string('cputime', 'report_profiling'), get_string('calls', 'report_profiling'),
get_string('memory', 'report_profiling'), get_string('comment', 'report_profiling'));
$table->define_columns($columns);
$table->define_headers($headers);
$table->sortable(true, 'timecreated', SORT_DESC);
$table->define_baseurl($baseurl);
$table->column_suppress('url');
$table->out(PROFILING_RUNSPERPAGE, true);
// Print the controller block with different options
echo profiling_list_controls($listurl);
}
// Footer.
echo $OUTPUT->footer();
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'report_profiling', language 'en', branch 'MOODLE_20_STABLE'
*
* @package report_profiling
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['calls'] = 'Function calls';
$string['cannotfindanyrunforurl'] = 'Sorry, cannot find any profiling run for the \'{$a}\' URL';
$string['cannotfindanyrunforrunid'] = 'Sorry, cannot find the \'{$a}\' profiling run';
$string['comment'] = 'Comment';
$string['differencesbetween2runsof'] = 'Differences between 2 runs of {$a}';
$string['executiontime'] = 'Execution time';
$string['cputime'] = 'CPU time';
$string['lastrunof'] = 'Summary of last run of {$a}';
$string['markreferencerun'] = 'Mark as reference run/comment';
$string['memory'] = 'Memory used';
$string['pluginname'] = 'Profiling runs';
$string['profilingfocusscript'] = 'Focus on profiling runs for the script: {$a}';
$string['profilingruns'] = 'Profiling runs';
$string['profilingrunsfor'] = 'Profiling runs for {$a}';
$string['referencerun'] = 'Reference run/comment';
$string['runid'] = 'Run ID';
$string['summaryof'] = 'Summary of {$a}';
$string['viewdetails'] = 'View profiling details';
$string['viewdiff'] = 'View profiling differences with last reference run';
$string['viewdiffdetails'] = 'View profiling diff details';
<?php
defined('MOODLE_INTERNAL') || die;
// profiling report, added to development
if (extension_loaded('xhprof') && function_exists('xhprof_enable') && !empty($CFG->profilingenabled)) {
$ADMIN->add('development', new admin_externalpage('reportprofiling', get_string('pluginname', 'report_profiling'), "$CFG->wwwroot/$CFG->admin/report/profiling/index.php", 'moodle/site:config'));
}
/* report_profiling styles */
.path-admin-report-profiling .profilingruntable .label {
font-weight: bold;
}
.path-admin-report-profiling .profiling_worse {
color: red;
}
.path-admin-report-profiling .profiling_better {
color: green;
}
.path-admin-report-profiling .profiling_same {
color: dimgrey;
}
.path-admin-report-profiling .profiling_important,
.path-admin-report-profiling .flexible .referencerun {
font-weight: bold;
}
.path-admin-report-profiling .flexible .r1 .cell {
background-color: whitesmoke;
}
.path-admin-report-profiling .flexible {
margin-left:auto;
margin-right:auto
}
......@@ -35,6 +35,44 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp->add(new admin_setting_configcheckbox('debugpageinfo', get_string('debugpageinfo', 'admin'), get_string('configdebugpageinfo', 'admin'), 0));
$ADMIN->add('development', $temp);
// "profiling" settingpage (conditionally if the 'xhprof' extension is available only)
if (extension_loaded('xhprof') && function_exists('xhprof_enable')) {
$temp = new admin_settingpage('profiling', get_string('profiling', 'admin'));
// Main profiling switch
$temp->add(new admin_setting_configcheckbox('profilingenabled', get_string('profilingenabled', 'admin'), get_string('profilingenabled_help', 'admin'), false));
// List of URLs that will be automatically profiled
$temp->add(new admin_setting_configtextarea('profilingincluded', get_string('profilingincluded', 'admin'), get_string('profilingincluded_help', 'admin'), ''));
// List of URLs that won't be profiled ever
$temp->add(new admin_setting_configtextarea('profilingexcluded', get_string('profilingexcluded', 'admin'), get_string('profilingexcluded_help', 'admin'), ''));
// Allow random profiling each XX requests
$temp->add(new admin_setting_configtext('profilingautofrec', get_string('profilingautofrec', 'admin'), get_string('profilingautofrec_help', 'admin'), 0, PARAM_INT));
// Allow PROFILEME/DONTPROFILEME GPC
$temp->add(new admin_setting_configcheckbox('profilingallowme', get_string('profilingallowme', 'admin'), get_string('profilingallowme_help', 'admin'), false));
// Allow PROFILEALL/PROFILEALLSTOP GPC
$temp->add(new admin_setting_configcheckbox('profilingallowall', get_string('profilingallowall', 'admin'), get_string('profilingallowall_help', 'admin'), false));
// TODO: Allow to skip PHP functions (XHPROF_FLAGS_NO_BUILTINS)
// TODO: Allow to skip call_user functions (ignored_functions array)
// Specify the life time (in minutes) of profiling runs
$temp->add(new admin_setting_configselect('profilinglifetime', get_string('profilinglifetime', 'admin'), get_string('profilinglifetime_help', 'admin'), 24*60, array(
0 => get_string('neverdeleteruns', 'admin'),
30*24*60 => get_string('numdays', '', 30),
15*24*60 => get_string('numdays', '', 15),
7*24*60 => get_string('numdays', '', 7),
4*24*60 => get_string('numdays', '', 4),
2*24*60 => get_string('numdays', '', 2),
24*60 => get_string('numhours', '', 24),
16*80 => get_string('numhours', '', 16),
8*60 => get_string('numhours', '', 8),
4*60 => get_string('numhours', '', 4),
2*60 => get_string('numhours', '', 2),
60 => get_string('numminutes', '', 60),
30 => get_string('numminutes', '', 30),
15 => get_string('numminutes', '', 15))));
// Add the 'profiling' page to admin block
$ADMIN->add('development', $temp);
}
// XMLDB editor
$ADMIN->add('development', new admin_externalpage('xmldbeditor', get_string('xmldbeditor'), "$CFG->wwwroot/$CFG->admin/xmldb/"));
......
......@@ -12,6 +12,7 @@ $temp->add(new admin_setting_configselect('gdversion', get_string('gdversion','a
'2' => get_string('gd2'))));
$temp->add(new admin_setting_configexecutable('pathtodu', get_string('pathtodu', 'admin'), get_string('configpathtodu', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('aspellpath', get_string('aspellpath', 'admin'), get_string('edhelpaspellpath'), ''));
$temp->add(new admin_setting_configexecutable('pathtodot', get_string('pathtodot', 'admin'), get_string('pathtodot_help', 'admin'), ''));
$ADMIN->add('server', $temp);
......
......@@ -735,6 +735,7 @@ $string['navigationupgrade'] = 'This upgrade introduces two new navigation block
$string['navcourselimit'] = 'Course limit';
$string['navshowallcourses'] = 'Show all courses';
$string['navshowcategories'] = 'Show course categories';
$string['neverdeleteruns'] = 'Never delete runs';
$string['nobookmarksforuser'] = 'You do not have any bookmarks.';
$string['nodatabase'] = 'No database';
$string['nodefaultuserrolelists'] = 'Don\'t return all default role users';
......@@ -766,6 +767,8 @@ $string['pathconvert'] = 'Path of <i>convert</i> binary';
$string['pathdvips'] = 'Path of <i>dvips</i> binary';
$string['pathlatex'] = 'Path of <i>latex</i> binary';
$string['pathtoclam'] = 'clam AV path';
$string['pathtodot'] = 'Path to dot';
$string['pathtodot_help'] = 'Path to dot. Probably something like /usr/bin/dot. To be able to generate graphics from DOT files, you must have installed the dot executable and point to it here. Note that, for now, this only used by the profiling features (Development->Profiling) built into Moodle.';
$string['pathtodu'] = 'Path to du';
$string['pathtopgdump'] = 'Path to pg_dump';
$string['pathtopgdumpdesc'] = 'This is only necessary to enter if you have more than one pg_dump on your system (for example if you have more than one version of postgresql installed)';
......@@ -801,6 +804,8 @@ $string['profiledefaultchecked'] = 'Checked by default';
$string['profiledeletecategory'] = 'Deleting a category';
$string['profiledeletefield'] = 'Deleting a field';
$string['profiledescription'] = 'Description of the field';
$string['profiledscript'] = 'This script has been profiled';
$string['profiledscriptview'] = 'View profiling information for this script';
$string['profileeditcategory'] = 'Editing category: {$a}';
$string['profileeditfield'] = 'Editing profile field: {$a}';
$string['profilefield'] = 'Profile field';
......@@ -836,6 +841,21 @@ $string['profilevisible_help'] = '* Not visible - For private data only viewable
$string['profilevisibleall'] = 'Visible to everyone';
$string['profilevisiblenone'] = 'Not visible';
$string['profilevisibleprivate'] = 'Visible to user';
$string['profiling'] = 'Profiling';
$string['profilingallowall'] = 'Continuous profiling';
$string['profilingallowall_help'] = 'If you enable this setting, then, at any moment, you can use the PROFILEALL parameter anywhere (PGC) to enable profiling for all the executed scripts along the Moodle session life. Analogously, you can use the PROFILEALLSTOP parameter to stop it.';
$string['profilingallowme'] = 'Selective profiling';
$string['profilingallowme_help'] = 'If you enable this setting, then, selectively, you can use the PROFILEME parameter anywhere (PGC) and profiling for that script will happen. Analogously, you can use the DONTPROFILEME parameter to prevent profiling to happen';
$string['profilingautofrec'] = 'Automatic profiling';
$string['profilingautofrec_help'] = 'By configuring this setting, some request (randomly, based on the frecuency specified - 1 of XXX) will be picked and automatically profiled, storing results for further analysis. Note that this way of profiling observes the include/exclude settings. Set it to 0 to disable automatic profiling.';
$string['profilingenabled'] = 'Enable profiling';
$string['profilingenabled_help'] = 'If you enable this setting, then profiling will be available in this site and you will be able to define its behavior by configuring the next options.';
$string['profilingexcluded'] = 'Exclude profiling';
$string['profilingexcluded_help'] = 'List of (comma separated, absolute skipping wwwroot, callable) URLs that will be excluded from being profiled from the ones defined by \'Profile these\' setting.';
$string['profilingincluded'] = 'Profile these';
$string['profilingincluded_help'] = 'List of (comma separated, absolute skipping wwwroot, callable) URLs that will be automatically profiled. Examples: /index.php, /course/view.php. Also accepts the * wildchar at any position. Examples: /mod/forum/*, /mod/*/view.php.';
$string['profilinglifetime'] = 'Keep profiling runs';
$string['profilinglifetime_help'] = 'Specify the time you want to keep information about old profiling runs. Older ones will be pruned periodically. Note that this excludes any profiling run marked as \'reference run\'.';
$string['protectusernames'] = 'Protect usernames';
$string['proxybypass'] = 'Proxy bypass hosts';
$string['proxyhost'] = 'Proxy host';
......
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/db" VERSION="20101026" COMMENT="XMLDB file for core Moodle tables"
<XMLDB PATH="lib/db" VERSION="20101121" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
......@@ -2688,7 +2688,7 @@
<INDEX NAME="backupid_contextid_component_filearea_itemid_ix" UNIQUE="false" FIELDS="backupid, contextid, component, filearea, itemid"/>
</INDEXES>
</TABLE>
<TABLE NAME="backup_logs" COMMENT="To store all the logs from backup and restore operations (by db logger)" PREVIOUS="backup_files_template" NEXT="course_published">
<TABLE NAME="backup_logs" COMMENT="To store all the logs from backup and restore operations (by db logger)" PREVIOUS="backup_files_template" NEXT="profiling">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="backupid"/>
<FIELD NAME="backupid" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" COMMENT="backupid the log record belongs to" PREVIOUS="id" NEXT="loglevel"/>
......@@ -2704,7 +2704,30 @@
<INDEX NAME="backupid-id" UNIQUE="true" FIELDS="backupid, id" COMMENT="for quick ordered retrieval by backupid"/>
</INDEXES>
</TABLE>
<TABLE NAME="course_published" COMMENT="Information about how and when an local courses were published to hubs" PREVIOUS="backup_logs">
<TABLE NAME="profiling" COMMENT="Stores the results of all the profiling runs" PREVIOUS="backup_logs" NEXT="course_published">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="runid"/>
<FIELD NAME="runid" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" COMMENT="the unique id for this run (as generated by xhprof)" PREVIOUS="id" NEXT="url"/>
<FIELD NAME="url" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="the url this profiling record is about (without wwwroot nor query params)" PREVIOUS="runid" NEXT="data"/>
<FIELD NAME="data" TYPE="text" LENGTH="big" NOTNULL="true" SEQUENCE="false" COMMENT="the raw data gathered by xhprof" PREVIOUS="url" NEXT="totalexecutiontime"/>
<FIELD NAME="totalexecutiontime" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="time (in microseconds) spent by the run" PREVIOUS="data" NEXT="totalcputime"/>
<FIELD NAME="totalcputime" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="time (in microseconds) spent by the CPU in this run" PREVIOUS="totalexecutiontime" NEXT="totalcalls"/>
<FIELD NAME="totalcalls" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Total number of calls performed by the run" PREVIOUS="totalcputime" NEXT="totalmemory"/>
<FIELD NAME="totalmemory" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="Total memory used byt the run" PREVIOUS="totalcalls" NEXT="runreference"/>
<FIELD NAME="runreference" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Is this run a reference one" PREVIOUS="totalmemory" NEXT="runcomment"/>
<FIELD NAME="runcomment" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="Brief comment for this run" PREVIOUS="runreference" NEXT="timecreated"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="unix timestap of the creation of this run" PREVIOUS="runcomment"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="runid_uk"/>
<KEY NAME="runid_uk" TYPE="unique" FIELDS="runid" PREVIOUS="primary"/>
</KEYS>
<INDEXES>
<INDEX NAME="url_runreference_ix" UNIQUE="false" FIELDS="url, runreference" NEXT="timecreated_runreference_ix"/>
<INDEX NAME="timecreated_runreference_ix" UNIQUE="false" FIELDS="timecreated, runreference" PREVIOUS="url_runreference_ix"/>
</INDEXES>
</TABLE>
<TABLE NAME="course_published" COMMENT="Information about how and when an local courses were published to hubs" PREVIOUS="profiling">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="huburl"/>
<FIELD NAME="huburl" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="the url of the &quot;registered on&quot; hub" PREVIOUS="id" NEXT="courseid"/>
......@@ -2720,4 +2743,4 @@
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
\ No newline at end of file
</XMLDB>
......@@ -5477,6 +5477,41 @@ WHERE gradeitemid IS NOT NULL AND grademax IS NOT NULL");
upgrade_main_savepoint(true, 2010111702);
}
if ($oldversion < 2010121401) {
// Define table profiling to be created
$table = new xmldb_table('profiling');
// Adding fields to table profiling
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('runid', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL, null, null);
$table->add_field('url', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
$table->add_field('data', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null);
$table->add_field('totalexecutiontime', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('totalcputime', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('totalcalls', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('totalmemory', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('runreference', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
$table->add_field('runcomment', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
// Adding keys to table profiling
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
$table->add_key('runid_uk', XMLDB_KEY_UNIQUE, array('runid'));
// Adding indexes to table profiling
$table->add_index('url_runreference_ix', XMLDB_INDEX_NOTUNIQUE, array('url', 'runreference'));
$table->add_index('timecreated_runreference_ix', XMLDB_INDEX_NOTUNIQUE, array('timecreated', 'runreference'));
// Conditionally launch create table for profiling
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
}
// Main savepoint reached
upgrade_main_savepoint(true, 2010121401);
}
return true;
}
......
......@@ -353,7 +353,7 @@ class core_renderer extends renderer_base {
* @return string HTML fragment.
*/
public function standard_footer_html() {
global $CFG;
global $CFG, $SCRIPT;
// This function is normally called from a layout.php file in {@link header()}
// but some of the content won't be known until later, so we return a placeholder
......@@ -367,6 +367,14 @@ class core_renderer extends renderer_base {
$output .= '<div class="performanceinfo pageinfo">This page is: ' . $this->page->debug_summary() . '</div>';
}
if (debugging(null, DEBUG_DEVELOPER) and has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) { // Only in developer mode
// Add link to profiling report if necessary
if (function_exists('profiling_is_running') && profiling_is_running()) {
$txt = get_string('profiledscript', 'admin');
$title = get_string('profiledscriptview', 'admin');
$url = $CFG->wwwroot . '/admin/report/profiling/index.php?script=' . urlencode($SCRIPT);
$link= '<a title="' . $title . '" href="' . $url . '">' . $txt . '</a>';
$output .= '<div class="profilingfooter">' . $link . '</div>';
}
$output .= '<div class="purgecaches"><a href="'.$CFG->wwwroot.'/admin/purgecaches.php?confirm=1&amp;sesskey='.sesskey().'">'.get_string('purgecaches', 'admin').'</a></div>';
}
if (!empty($CFG->debugvalidators)) {
......
......@@ -646,7 +646,6 @@ if (isset($_SERVER['PHP_SELF'])) {
// initialise ME's
initialise_fullme();
// init session prevention flag - this is defined on pages that do not want session
if (CLI_SCRIPT) {
// no sessions in CLI scripts possible
......@@ -669,6 +668,13 @@ session_get_instance();
$SESSION = &$_SESSION['SESSION'];
$USER = &$_SESSION['USER'];
// include and start profiling if needed, and register profiling_stop as shutdown function
if (!empty($CFG->profilingenabled)) {
require_once($CFG->libdir . '/xhprof/xhprof_moodle.php');
profiling_start();
register_shutdown_function('profiling_stop');
}
// Process theme change in the URL.
if (!empty($CFG->allowthemechangeonurl) and !empty($_GET['theme'])) {
// we have to use _GET directly because we do not want this to interfere with _POST
......
......@@ -294,6 +294,13 @@
<version>1.10</version>
<licenseversion></licenseversion>
</library>
<library>
<location>xhprof</location>
<name>XHProf</name>
<license>Apache</license>
<version>0.9.2</version>
<licenseversion>2.0</licenseversion>
</library>
<library>
<location>xmlize.php</location>
<name>XMLize</name>
......
Modification History:
*** NOTE ***
DO NOT UPDATE THIS FILE. UPDATE package.xml INSTEAD.
This file contains the CHANGELOG for the initial release. For subsequent
releases, the CHANGLELOG is maintained in the package.xml file itself.
Please edit package.xml instead.
************
03/02/2008 kannan, checkin xhprof_html/ and xhprof_lib/ directories.
cjiang [These contain PHP sources for the UI as well
as various supporting libraries to compute
"flat" info, diff reports, aggregate results
of multiple runs, typeahead support, etc.]
02/20/2008 kannan add basic sanity tests for the extension
02/19/2008 kannan register constants for optional profiler flags;
add xhprof.output_dir ini setting.
01/22/2008 ps port cpu affinity functions to FreeBSD
01/15/2008 kannan intercept builtins even if zend_execute_internal
were null to begin with
01/14/2008 kannan track builtins by default;
fix compiler warnings with fwd decls
12/22/2008 cjiang Further refactoring of the code for open sourcing:
(1). Remove level 1 profiling mode.
(2). Add xhprof_sample_enable, xhprof_sample_disable.
(3). Unifiy function and global variable prefix.
(4). Group relevant functions together.
(5). Migrate change history to CHANAGELOG file.
12/19/2008 kannan First step refactoring for open sourcing:
(1). Put basic direcotry structure
(2). Rename extension and function names
(3). Add LICENCE header.
06/17/2008 veeve use cycle_timer() for XHPROF_MODE_SAMPLED
03/27/2008 cjiang Add a 'hash-based' filter to reduce the number
of expensive call-stack tranversal on recursion
detection.
03/17/2008 kannan must not keep state on C stack to handle
exit (which causes _zend_bailout to longjmp
02/25/2008 kannan add xhprof_flags to toggle various metric
collections (buitins on/off, cpu metric on/off
memory stats on/off)
02/14/2008 cjiang Use cycle_timer based on 'rdtsc' instruction
on x86 machines to replace gettimeofday. rdtsc
is extremely cheap compared with gettimeofday
or getrusage.
12/06/2007 veeve bump version 1.1.2,
added hp_global_t
added mode callbacks, made modes extensible
added sampler mode
12/05/2007 veeve added doc; house cleaning
11/28/2007 kannan split include accounting into load/run_init
11/09/2007 kannan memory usage profiling
10/27/2007 kannan handle recursive calls, "include" operations
10/20/2007 kannan add hierarchical profiling; incl vs. exclusive
function times; browser based UI; diff and
aggregation support
10/10/2007 hzhao creation (flat function profiles)
Authors:
Haiping Zhao hzhao@facebook.com
Kannan Muthukkaruppan kannan@facebook.com
Venkat Venkataramani veeve@facebook.com
Changhao Jiang cjiang@facebook.com
Originally developed at Facebook, XHProf was open sourced in Mar, 2009.
Creators:
Changhao Jiang