Commit c646dd26 authored by Eloy Lafuente's avatar Eloy Lafuente
Browse files

MDL-26891 profiling - earlier runs

This allows profiling to be started earlier in the
setup.php execution, by configuring everything in
the config.php file. That way some interesting code
is also profiled, like DB connections, load of config records...

100% compatible with normal profiling and enabled via
special setting $CFG->earlyprofilingenabled

Example (to be put on config.php):

$CFG->earlyprofilingenabled = true;
$CFG->profilingautofrec = 3;
$CFG->profilingincluded = '/*';
$CFG->profilingallowme = true;

(to enable early profiling for 1/3 of any requests while also
allowing to use the PROFILEME PGC)
parent dae6b38c
......@@ -3,6 +3,6 @@
defined('MOODLE_INTERNAL') || die;
// profiling report, added to development
if (extension_loaded('xhprof') && function_exists('xhprof_enable') && !empty($CFG->profilingenabled)) {
if (extension_loaded('xhprof') && function_exists('xhprof_enable') && (!empty($CFG->profilingenabled) || !empty($CFG->earlyprofilingenabled))) {
$ADMIN->add('development', new admin_externalpage('reportprofiling', get_string('pluginname', 'report_profiling'), "$CFG->wwwroot/$CFG->admin/report/profiling/index.php", 'moodle/site:config'));
}
......@@ -297,6 +297,13 @@ $CFG->admin = 'admin';
// Print to footer (works with the default theme)
// define('MDL_PERFTOFOOT', true);
//
// Enable earlier profiling that causes more code to be covered
// on every request (db connections, config load, other inits...).
// Requires extra configuration to be defined in config.php like:
// profilingincluded, profilingexcluded, profilingautofrec,
// profilingallowme, profilingallowall, profilinglifetime
// $CFG->earlyprofilingenabled = true;
//
// Force displayed usernames
// A little hack to anonymise user names for all students. If you set these
// then all non-teachers will always see these for every person.
......
......@@ -228,6 +228,14 @@ if (!defined('MOODLE_INTERNAL')) { // necessary because cli installer has to def
define('MOODLE_INTERNAL', true);
}
// Early profiling start, based exclusively on config.php $CFG settings
if (!empty($CFG->earlyprofilingenabled)) {
require_once($CFG->libdir . '/xhprof/xhprof_moodle.php');
if (profiling_start()) {
register_shutdown_function('profiling_stop');
}
}
/**
* Database connection. Used for all access to the database.
* @global moodle_database $DB
......@@ -669,11 +677,12 @@ session_get_instance();
$SESSION = &$_SESSION['SESSION'];
$USER = &$_SESSION['USER'];
// include and start profiling if needed, and register profiling_stop as shutdown function
// Late profiling, only happening if early one wasn't started
if (!empty($CFG->profilingenabled)) {
require_once($CFG->libdir . '/xhprof/xhprof_moodle.php');
profiling_start();
register_shutdown_function('profiling_stop');
if (profiling_start()) {
register_shutdown_function('profiling_stop');
}
}
// Process theme change in the URL.
......
......@@ -25,9 +25,6 @@ TODO:
* export/import profiling runs: Allow to pick any profile record, encapsulate
it into some serialized/encoded way and allow download/upload. It requires
DB changes in order to be able to specify the source of each record (own/imported).
* move profiling start to earlier place: detect if all the needed $CFG->profilingXXX variables
have been defined in config.php file and if that condition is fullfilled, start profiling
@ the very first lines of setup.php (as early as possible).
* improvements to the listing mode: various commodity details like:
- allow to filter by various criteria
- inline (and ajax) editing of reference/comment and deleting
......@@ -38,4 +35,5 @@ TODO:
- cpu times
(all them are right now enabled for everybody by default)
20101122 - Eloy Lafuente (stronk7): Original import of 0.9.2 release
20101122 - MDL-24600 - Eloy Lafuente (stronk7): Original import of 0.9.2 release
20110318 - MDL-26891 - Eloy Lafuente (stronk7): Implemented earlier profiling runs
......@@ -69,7 +69,7 @@ function profiling_start() {
}
// If profiling isn't enabled, nothing to start
if (!$CFG->profilingenabled) {
if (empty($CFG->profilingenabled) && empty($CFG->earlyprofilingenabled)) {
return false;
}
......@@ -78,19 +78,22 @@ function profiling_start() {
return false;
}
// Set script (from global if available, else our own)
$script = !empty($SCRIPT) ? $SCRIPT : profiling_get_script();
// Get PGC variables
$check = 'PROFILEME';
$profileme = isset($_POST[$check]) || isset($_GET[$check]) || isset($_COOKIE[$check]) ? true : false;
$profileme = $profileme && $CFG->profilingallowme;
$profileme = $profileme && !empty($CFG->profilingallowme);
$check = 'DONTPROFILEME';
$dontprofileme = isset($_POST[$check]) || isset($_GET[$check]) || isset($_COOKIE[$check]) ? true : false;
$dontprofileme = $dontprofileme && $CFG->profilingallowme;
$dontprofileme = $dontprofileme && !empty($CFG->profilingallowme);
$check = 'PROFILEALL';
$profileall = isset($_POST[$check]) || isset($_GET[$check]) || isset($_COOKIE[$check]) ? true : false;
$profileall = $profileall && $CFG->profilingallowall;
$profileall = $profileall && !empty($CFG->profilingallowall);
$check = 'PROFILEALLSTOP';
$profileallstop = isset($_POST[$check]) || isset($_GET[$check]) || isset($_COOKIE[$check]) ? true : false;
$profileallstop = $profileallstop && $CFG->profilingallowall;
$profileallstop = $profileallstop && !empty($CFG->profilingallowall);
// DONTPROFILEME detected, nothing to start
if ($dontprofileme) {
......@@ -98,12 +101,12 @@ function profiling_start() {
}
// PROFILEALLSTOP detected, clean the mark in seesion and continue
if ($profileallstop) {
if ($profileallstop && !empty($SESSION)) {
unset($SESSION->profileall);
}
// PROFILEALL detected, set the mark in session and continue
if ($profileall) {
if ($profileall && !empty($SESSION)) {
$SESSION->profileall = true;
// SESSION->profileall detected, set $profileall
......@@ -113,21 +116,23 @@ function profiling_start() {
// Evaluate automatic (random) profiling if necessary
$profileauto = false;
if ($CFG->profilingautofrec) {
if (!empty($CFG->profilingautofrec)) {
$profileauto = (mt_rand(1, $CFG->profilingautofrec) === 1);
}
// See if the $SCRIPT matches any of the included patterns
$profileincluded = profiling_string_matches($SCRIPT, $CFG->profilingincluded);
// See if the $script matches any of the included patterns
$included = empty($CFG->profilingincluded) ? '' : $CFG->profilingincluded;
$profileincluded = profiling_string_matches($script, $included);
// See if the $SCRIPT matches any of the excluded patterns
$profileexcluded = profiling_string_matches($SCRIPT, $CFG->profilingexcluded);
// See if the $script matches any of the excluded patterns
$excluded = empty($CFG->profilingexcluded) ? '' : $CFG->profilingexcluded;
$profileexcluded = profiling_string_matches($script, $excluded);
// Decide if profile auto must happen (observe matchings)
$profileauto = $profileauto && $profileincluded && !$profileexcluded;
// Decide if profile by match must happen (only if profileauto is disabled)
$profilematch = $profileincluded && !$profileexcluded && !$CFG->profilingautofrec;
$profilematch = $profileincluded && !$profileexcluded && empty($CFG->profilingautofrec);
// If not auto, me, all, match have been detected, nothing to do
if (!$profileauto && !$profileme && !$profileall && !$profilematch) {
......@@ -138,6 +143,9 @@ function profiling_start() {
$ignore = array('call_user_func', 'call_user_func_array');
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY, array('ignored_functions' => $ignore));
profiling_is_running(true);
// Started, return true
return true;
}
/**
......@@ -152,7 +160,7 @@ function profiling_stop() {
}
// If profiling isn't enabled, nothing to stop
if (!$CFG->profilingenabled) {
if (empty($CFG->profilingenabled) && empty($CFG->earlyprofilingenabled)) {
return false;
}
......@@ -161,17 +169,23 @@ function profiling_stop() {
return false;
}
// Set script (from global if available, else our own)
$script = !empty($SCRIPT) ? $SCRIPT : profiling_get_script();
// Arrived here, profiling is running, stop and save everything
profiling_is_running(false);
$data = xhprof_disable();
$run = new moodle_xhprofrun();
$run->prepare_run($SCRIPT);
$run->prepare_run($script);
$runid = $run->save_run($data, null);
profiling_is_saved(true);
// Prune old runs
profiling_prune_old_runs($runid);
// Finished, return true
return true;
}
function profiling_prune_old_runs($exception = 0) {
......@@ -190,6 +204,34 @@ function profiling_prune_old_runs($exception = 0) {
runid != :exception', $params);
}
/**
* Returns the path to the php script being requested
*
* Note this function is a partial copy of initialise_fullme() and
* setup_get_remote_url(), in charge of setting $FULLME, $SCRIPT and
* friends. To be used by early profiling runs in situations where
* $SCRIPT isn't defined yet
*
* @return string absolute path (wwwroot based) of the script being executed
*/
function profiling_get_script() {
global $CFG;
$wwwroot = parse_url($CFG->wwwroot);
if (!isset($wwwroot['path'])) {
$wwwroot['path'] = '';
}
$wwwroot['path'] .= '/';
$path = $_SERVER['SCRIPT_NAME'];
if (strpos($path, $wwwroot['path']) === 0) {
return substr($path, strlen($wwwroot['path']) - 1);
}
return '';
}
function profiling_urls($report, $runid, $runid2 = null) {
global $CFG;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment