From ab130a0b5fb6b695a3373821097b305719c8834a Mon Sep 17 00:00:00 2001 From: skodak Date: Mon, 16 Jun 2008 21:01:54 +0000 Subject: [PATCH] MDL-15273 basic read/write perf counter in moodle_database --- admin/cron.php | 16 +++++-------- lib/dml/adodb_moodle_database.php | 26 ++++++++++++++++++--- lib/dml/moodle_database.php | 19 ++++++++++++++- lib/dml/mssql_adodb_moodle_database.php | 9 +++++-- lib/dml/mysqli_adodb_moodle_database.php | 5 ++++ lib/dml/oci8po_adodb_moodle_database.php | 13 ++++++++++- lib/dml/postgres7_adodb_moodle_database.php | 12 ++++++++++ lib/moodlelib.php | 14 +++++------ lib/setuplib.php | 3 +-- 9 files changed, 90 insertions(+), 27 deletions(-) diff --git a/admin/cron.php b/admin/cron.php index 092e9d10d6843..47c8153a1a641 100644 --- a/admin/cron.php +++ b/admin/cron.php @@ -110,17 +110,15 @@ if (function_exists($cron_function)) { mtrace("Processing module function $cron_function ...", ''); $pre_dbqueries = null; - if (!empty($PERF->dbqueries)) { - $pre_dbqueries = $PERF->dbqueries; - $pre_time = microtime(1); - } + $pre_dbqueries = $DB->perf_get_reads(); + $pre_time = microtime(1); if ($cron_function()) { if (!$DB->set_field("modules", "lastcron", $timenow, array("id"=>$mod->id))) { mtrace("Error: could not update timestamp for $mod->fullname"); } } if (isset($pre_dbqueries)) { - mtrace("... used " . ($PERF->dbqueries - $pre_dbqueries) . " dbqueries"); + mtrace("... used " . ($DB->perf_get_reads() - $pre_dbqueries) . " dbqueries"); mtrace("... used " . (microtime(1) - $pre_time) . " seconds"); } /// Reset possible changes by modules to time_limit. MDL-11597 @@ -173,13 +171,11 @@ $cronfunction = 'report_'.$report.'_cron'; mtrace('Processing cron function for '.$report.'...', ''); $pre_dbqueries = null; - if (!empty($PERF->dbqueries)) { - $pre_dbqueries = $PERF->dbqueries; - $pre_time = microtime(true); - } + $pre_dbqueries = $DB->perf_get_reads(); + $pre_time = microtime(true); $cronfunction(); if (isset($pre_dbqueries)) { - mtrace("... used " . ($PERF->dbqueries - $pre_dbqueries) . " dbqueries"); + mtrace("... used " . ($DB->perf_get_reads() - $pre_dbqueries) . " dbqueries"); mtrace("... used " . round(microtime(true) - $pre_time, 2) . " seconds"); } mtrace('done.'); diff --git a/lib/dml/adodb_moodle_database.php b/lib/dml/adodb_moodle_database.php index 8e835f7749df4..d3c34cfb9e436 100644 --- a/lib/dml/adodb_moodle_database.php +++ b/lib/dml/adodb_moodle_database.php @@ -95,12 +95,12 @@ public function dispose() { parent::dispose(); } - //TODO: make all dblibraries return this info in a structured way (new server_info class or so, like database_column_info class) /** * Returns database server info array * @return array */ public function get_server_info() { + //TODO: make all dblibraries return this info in a structured way (new server_info class or so, like database_column_info class) return $this->adodb->ServerInfo(); } @@ -126,6 +126,7 @@ public function get_tables() { * @return array of arrays */ public function get_indexes($table) { + $this->reads++; if (!$indexes = $this->adodb->MetaIndexes($this->prefix.$table)) { return array(); } @@ -145,6 +146,7 @@ public function get_columns($table, $usecache=true) { return $this->columns[$table]; } + $this->reads++; if (!$columns = $this->adodb->MetaColumns($this->prefix.$table)) { return array(); } @@ -203,6 +205,8 @@ public function set_logging($state) { * @return bool success */ public function change_database_structure($sql) { + $this->writes++; + if ($rs = $this->adodb->Execute($sql)) { $result = true; } else { @@ -222,7 +226,6 @@ public function change_database_structure($sql) { * @return bool success */ public function execute($sql, array $params=null) { - list($sql, $params, $type) = $this->fix_sql_params($sql, $params); if (strpos($sql, ';') !== false) { @@ -230,6 +233,8 @@ public function execute($sql, array $params=null) { return false; } + $this->writes++; + if ($rs = $this->adodb->Execute($sql, $params)) { $result = true; $rs->Close(); @@ -240,7 +245,6 @@ public function execute($sql, array $params=null) { return $result; } - //TODO: do we want the *_raw() functions being public? I see the benefits but... won't that cause problems. To decide. /** * Insert new record into database, as fast as possible, no safety checks, lobs not supported. * @param string $table name @@ -250,6 +254,8 @@ public function execute($sql, array $params=null) { * @return mixed success or new id */ public function insert_record_raw($table, $params, $returnid=true, $bulk=false) { + //TODO: do we want the *_raw() functions being public? I see the benefits but... won't that cause problems. To decide. + if (!is_array($params)) { $params = (array)$params; } @@ -259,6 +265,8 @@ public function insert_record_raw($table, $params, $returnid=true, $bulk=false) return false; } + $this->writes++; + $fields = implode(',', array_keys($params)); $qms = array_fill(0, count($params), '?'); $qms = implode(',', $qms); @@ -299,6 +307,8 @@ public function update_record_raw($table, $params, $bulk=false) { return false; } + $this->writes++; + $sets = array(); foreach ($params as $field=>$value) { $sets[] = "$field = ?"; @@ -332,6 +342,8 @@ public function delete_records_select($table, $select, array $params=null) { list($sql, $params, $type) = $this->fix_sql_params($sql, $params); + $this->writes++; + $result = false; if ($rs = $this->adodb->Execute($sql, $params)) { $result = true; @@ -359,6 +371,8 @@ public function delete_records_select($table, $select, array $params=null) { public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) { list($sql, $params, $type) = $this->fix_sql_params($sql, $params); + $this->reads++; + if ($limitfrom || $limitnum) { ///Special case, 0 must be -1 for ADOdb $limitfrom = empty($limitfrom) ? -1 : $limitfrom; @@ -394,6 +408,9 @@ protected function create_recordset($rs) { */ public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) { list($sql, $params, $type) = $this->fix_sql_params($sql, $params); + + $this->reads++; + if ($limitfrom || $limitnum) { ///Special case, 0 must be -1 for ADOdb $limitfrom = empty($limitfrom) ? -1 : $limitfrom; @@ -420,6 +437,9 @@ public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnu */ public function get_fieldset_sql($sql, array $params=null) { list($sql, $params, $type) = $this->fix_sql_params($sql, $params); + + $this->reads++; + if (!$rs = $this->adodb->Execute($sql, $params)) { $this->report_error($sql, $params); return false; diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index db6e0fd72aee5..bb9ab0aaf8d63 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -48,7 +48,16 @@ abstract class moodle_database { */ protected $dboptions; - // TODO: perf stuff goes here + /** + * The database reads (performance counter). + */ + protected $reads = 0; + + /** + * The database writes (performance counter). + */ + protected $writes = 0; + // TODO: do we really need record caching?? /** @@ -1393,4 +1402,12 @@ public function commit_sql() { public function rollback_sql() { return true; } + + public function perf_get_reads() { + return $this->reads; + } + + public function perf_get_writes() { + return $this->writes; + } } diff --git a/lib/dml/mssql_adodb_moodle_database.php b/lib/dml/mssql_adodb_moodle_database.php index d31c37e245d7e..a635231ea64f8 100644 --- a/lib/dml/mssql_adodb_moodle_database.php +++ b/lib/dml/mssql_adodb_moodle_database.php @@ -44,10 +44,10 @@ protected function configure_dbconnection() { /// No need to set charset. It must be specified in the driver conf /// Allow quoted identifiers - $this->adodb->Execute('SET QUOTED_IDENTIFIER ON'); + $this->adodb->Execute('SET QUOTED_IDENTIFIER ON'); /// Force ANSI nulls so the NULL check was done by IS NULL and NOT IS NULL /// instead of equal(=) and distinct(<>) simbols - $this->adodb->Execute('SET ANSI_NULLS ON'); + $this->adodb->Execute('SET ANSI_NULLS ON'); return true; } @@ -192,6 +192,7 @@ public function update_record($table, $dataobject, $bulk=false) { } foreach ($blobs as $key=>$value) { + $this->writes++; if (!$this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = {$dataobject->id}")) { return false; } @@ -223,6 +224,7 @@ public function set_field_select($table, $newfield, $newvalue, $select, array $p if ($column->meta_type == 'B') { /// If the column is a BLOB (IMAGE) /// Update BLOB column and return $select = $this->emulate_bound_params($select, $params); // adodb does not use bound parameters for blob updates :-( + $this->writes++; return $this->adodb->UpdateBlob($this->prefix.$table, $newfield, $newvalue, $select); } @@ -243,6 +245,8 @@ public function set_field_select($table, $newfield, $newvalue, $select, array $p } $sql = "UPDATE {$this->prefix}$table SET $newfield WHERE $select"; + $this->writes++; + if (!$rs = $this->adodb->Execute($sql, $params)) { $this->report_error($sql, $params); return false; @@ -309,6 +313,7 @@ public function insert_record($table, $dataobject, $returnid=true, $bulk=false) foreach ($blobs as $key=>$value) { + $this->writes++; if (!$this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id")) { return false; } diff --git a/lib/dml/mysqli_adodb_moodle_database.php b/lib/dml/mysqli_adodb_moodle_database.php index c7515f5cc3223..360a92397da28 100644 --- a/lib/dml/mysqli_adodb_moodle_database.php +++ b/lib/dml/mysqli_adodb_moodle_database.php @@ -94,6 +94,7 @@ protected function allowed_param_types() { * @return bool true if db in unicode mode */ function setup_is_unicodedb() { + $this->reads++; $rs = $this->adodb->Execute("SHOW LOCAL VARIABLES LIKE 'character_set_database'"); if ($rs && !$rs->EOF) { $records = $rs->GetAssoc(true); @@ -111,8 +112,10 @@ function setup_is_unicodedb() { */ public function change_db_encoding() { // try forcing utf8 collation, if mysql db and no tables present + $this->reads++; if (!$this->adodb->Metatables()) { $SQL = 'ALTER DATABASE '.$this->dbname.' CHARACTER SET utf8'; + $this->writes++; $this->adodb->Execute($SQL); if ($this->setup_is_unicodedb()) { $this->configure_dbconnection(); @@ -242,6 +245,8 @@ public function set_field_select($table, $newfield, $newvalue, $select, array $p } $sql = "UPDATE {$this->prefix}$table SET $newfield $select"; + $this->writes++; + if (!$rs = $this->adodb->Execute($sql, $params)) { $this->report_error($sql, $params); return false; diff --git a/lib/dml/oci8po_adodb_moodle_database.php b/lib/dml/oci8po_adodb_moodle_database.php index 449adcfd7eb97..bc756f7cc5027 100644 --- a/lib/dml/oci8po_adodb_moodle_database.php +++ b/lib/dml/oci8po_adodb_moodle_database.php @@ -107,6 +107,7 @@ protected function allowed_param_types() { * @return bool true if db in unicode mode */ function setup_is_unicodedb() { + $this->reads++; $rs = $this->adodb->Execute("SELECT parameter, value FROM nls_database_parameters where parameter = 'NLS_CHARACTERSET'"); if ($rs && !$rs->EOF) { $encoding = $rs->fields['value']; @@ -182,7 +183,7 @@ public function sql_isempty($tablename, $fieldname, $nullablefield, $textfield) return " $fieldname IS NULL "; /// empties in nullable fields are stored as } else { /// NULLs if ($textfield) { - return " ".sql_compare_text($fieldname)." = ' ' "; /// oracle_dirty_hack inserts 1-whitespace + return " ".$this->sql_compare_text($fieldname)." = ' ' "; /// oracle_dirty_hack inserts 1-whitespace } else { /// in NOT NULL varchar and text columns so return " $fieldname = ' ' "; /// we need to look for that in any situation } @@ -267,12 +268,14 @@ public function update_record($table, $dataobject, $bulk=false) { } foreach ($blobs as $key=>$value) { + $this->writes++; if (!$this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = {$dataobject->id}")) { return false; } } foreach ($clobs as $key=>$value) { + $this->writes++; if (!$this->adodb->UpdateClob($this->prefix.$table, $key, $value, "id = {$dataobject->id}")) { return false; } @@ -350,12 +353,14 @@ public function insert_record($table, $dataobject, $returnid=true, $bulk=false) } foreach ($blobs as $key=>$value) { + $this->writes++; if (!$this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id")) { return false; } } foreach ($clobs as $key=>$value) { + $this->writes++; if (!$this->adodb->UpdateClob($this->prefix.$table, $key, $value, "id = $id")) { return false; } @@ -391,12 +396,14 @@ public function set_field_select($table, $newfield, $newvalue, $select, array $p if ($column->meta_type == 'B') { /// If the column is a BLOB /// Update BLOB column and return $select = $this->emulate_bound_params($select, $params); // adodb does not use bound parameters for blob updates :-( + $this->writes++; return $this->adodb->UpdateBlob($this->prefix.$table, $newfield, $newvalue, $select); } if ($column->meta_type == 'X' && strlen($newvalue) > 4000) { /// If the column is a CLOB with lenght > 4000 /// Update BLOB column and return $select = $this->emulate_bound_params($select, $params); // adodb does not use bound parameters for blob updates :-( + $this->writes++; return $this->adodb->UpdateClob($this->prefix.$table, $newfield, $newvalue, $select); } @@ -417,6 +424,7 @@ public function set_field_select($table, $newfield, $newvalue, $select, array $p } $sql = "UPDATE {$this->prefix}$table SET $newfield WHERE $select"; + $this->writes++; if (!$rs = $this->adodb->Execute($sql, $params)) { $this->report_error($sql, $params); return false; @@ -442,6 +450,7 @@ public function insert_record_raw($table, $params, $returnid=true, $bulk=false) if ($returnid) { $dbman = $this->get_manager(); $xmldb_table = new xmldb_table($table); + $this->reads++; $seqname = $dbman->find_sequence_name($xmldb_table); if (!$seqname) { /// Fallback, seqname not found, something is wrong. Inform and use the alternative getNameForObject() method @@ -449,6 +458,7 @@ public function insert_record_raw($table, $params, $returnid=true, $bulk=false) $generator->setPrefix($this->getPrefix()); $seqname = $generator->getNameForObject($table, 'id', 'seq'); } + $this->reads++; if ($nextval = $this->adodb->GenID($seqname)) { $params['id'] = (int)$nextval; } @@ -478,6 +488,7 @@ public function insert_record_raw($table, $params, $returnid=true, $bulk=false) $sql = "INSERT INTO {$this->prefix}$table ($fields) VALUES($qms)"; + $this->writes++; if (!$rs = $this->adodb->Execute($sql, $params)) { $this->report_error($sql, $params); return false; diff --git a/lib/dml/postgres7_adodb_moodle_database.php b/lib/dml/postgres7_adodb_moodle_database.php index f560792834d23..29aaedde0446d 100644 --- a/lib/dml/postgres7_adodb_moodle_database.php +++ b/lib/dml/postgres7_adodb_moodle_database.php @@ -105,6 +105,7 @@ public function get_columns($table, $usecache=true) { return $this->columns[$table]; } + $this->reads++; if (!$columns = $this->adodb->MetaColumns($this->prefix.$table)) { return array(); } @@ -139,6 +140,7 @@ public function get_columns($table, $usecache=true) { */ function setup_is_unicodedb() { /// Get PostgreSQL server_encoding value + $this->reads++; $rs = $this->adodb->Execute("SHOW server_encoding"); if ($rs && !$rs->EOF) { $encoding = $rs->fields['server_encoding']; @@ -170,6 +172,7 @@ public function insert_record_raw($table, $params, $returnid=true, $bulk=false) } unset($params['id']); if ($returnid) { + $this->reads++; $seqname = "{$this->prefix}{$table}_id_seq"; if ($nextval = $this->adodb->GenID($seqname)) { $params['id'] = (int)$nextval; @@ -186,6 +189,8 @@ public function insert_record_raw($table, $params, $returnid=true, $bulk=false) $sql = "INSERT INTO {$this->prefix}$table ($fields) VALUES($qms)"; + $this->writes++; + if (!$rs = $this->adodb->Execute($sql, $params)) { $this->report_error($sql, $params); return false; @@ -199,6 +204,8 @@ public function insert_record_raw($table, $params, $returnid=true, $bulk=false) $oid = $this->adodb->Insert_ID(); + $this->reads++; + // try to get the primary key based on id $sql = "SELECT id FROM {$this->prefix}$table WHERE oid = $oid"; if ( ($rs = $this->adodb->Execute($sql)) @@ -271,6 +278,7 @@ public function insert_record($table, $dataobject, $returnid=true, $bulk=false) } foreach ($blobs as $key=>$value) { + $this->writes++; if (!$this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id", 'BLOB')) { // adodb does not use bound parameters for blob updates :-( return false; } @@ -340,6 +348,7 @@ public function update_record($table, $dataobject, $bulk=false) { } foreach ($blobs as $key=>$value) { + $this->writes++; if (!$this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id", 'BLOB')) { // adodb does not use bound parameters for blob updates :-( return false; } @@ -368,6 +377,7 @@ public function set_field_select($table, $newfield, $newvalue, $select, array $p if ($column->meta_type == 'B') { /// update blobs and return $select = $this->emulate_bound_params($select, $params); // adodb does not use bound parameters for blob updates :-( + $this->writes++; if (!$this->adodb->UpdateBlob($this->prefix.$table, $newfield, $newvalue, $select, 'BLOB')) { return false; } @@ -395,6 +405,8 @@ public function set_field_select($table, $newfield, $newvalue, $select, array $p } $sql = "UPDATE {$this->prefix}$table SET $newfield $select"; + $this->writes++; + if (!$rs = $this->adodb->Execute($sql, $params)) { $this->report_error($sql, $params); return false; diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 4259458e0114c..4ddc8324ee56f 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -7539,7 +7539,7 @@ function array_is_nested($array) { *** **/ function get_performance_info() { - global $CFG, $PERF; + global $CFG, $PERF, $DB; $info = array(); $info['html'] = ''; // holds userfriendly HTML representation @@ -7569,18 +7569,16 @@ function get_performance_info() { $info['html'] .= 'Included '.$info['includecount'].' files '; $info['txt'] .= 'includecount: '.$info['includecount'].' '; - if (!empty($PERF->dbqueries)) { - $info['dbqueries'] = $PERF->dbqueries; - $info['html'] .= 'DB queries '.$info['dbqueries'].' '; - $info['txt'] .= 'dbqueries: '.$info['dbqueries'].' '; - } - if (!empty($PERF->logwrites)) { $info['logwrites'] = $PERF->logwrites; - $info['html'] .= 'Log writes '.$info['logwrites'].' '; + $info['html'] .= 'Log DB writes '.$info['logwrites'].' '; $info['txt'] .= 'logwrites: '.$info['logwrites'].' '; } + $info['dbqueries'] = $DB->perf_get_reads().'/'.($DB->perf_get_writes() - $PERF->logwrites); + $info['html'] .= 'DB reads/writes: '.$info['dbqueries'].' '; + $info['txt'] .= 'db reads/writes: '.$info['dbqueries'].' '; + if (!empty($PERF->profiling) && $PERF->profiling) { require_once($CFG->dirroot .'/lib/profilerlib.php'); $info['html'] .= ''.Profiler::get_profiling(array('-R')).''; diff --git a/lib/setuplib.php b/lib/setuplib.php index 014bf64e8944c..b4bd86dc29de0 100644 --- a/lib/setuplib.php +++ b/lib/setuplib.php @@ -69,8 +69,7 @@ function init_performance_info() { global $PERF, $CFG, $USER; - $PERF = new Object; - $PERF->dbqueries = 0; + $PERF = new object(); $PERF->logwrites = 0; if (function_exists('microtime')) { $PERF->starttime = microtime();