Aaron Schulz has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/185342

Change subject: Added query/connection expectation support to 
TransactionProfiler
......................................................................

Added query/connection expectation support to TransactionProfiler

* Master connections/writes on read requests will now be logged to get 
visibility
  into code the reduces performance and site availability.

Change-Id: Ic2ae95c33facbb54e062aef2ce67d6182caa044a
---
M includes/MediaWiki.php
M includes/db/Database.php
M includes/profiler/TransactionProfiler.php
3 files changed, 107 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/42/185342/1

diff --git a/includes/MediaWiki.php b/includes/MediaWiki.php
index d94443b..7789bcf 100644
--- a/includes/MediaWiki.php
+++ b/includes/MediaWiki.php
@@ -485,6 +485,16 @@
                $action = $this->getAction();
                $wgTitle = $title;
 
+               // Aside from rollback, master queries should not happen on GET 
requests.
+               // Periodic or "in passing" updates on GET should use the job 
queue.
+               if ( !$request->wasPosted()
+                       && in_array( $action, array( 'view', 'edit', 'history' 
) )
+               ) {
+                       $trxProfiler = 
Profiler::instance()->getTransactionProfiler();
+                       $trxProfiler->setExpectation( 'masterConns', 0, 
__METHOD__ );
+                       $trxProfiler->setExpectation( 'writes', 0, __METHOD__ );
+               }
+
                // If the user has forceHTTPS set to true, or if the user
                // is in a group requiring HTTPS, or if they have the HTTPS
                // preference set, redirect them to HTTPS.
diff --git a/includes/db/Database.php b/includes/db/Database.php
index 054f27a..0e24bc9 100644
--- a/includes/db/Database.php
+++ b/includes/db/Database.php
@@ -817,6 +817,10 @@
                if ( $user ) {
                        $this->open( $server, $user, $password, $dbName );
                }
+
+               $isMaster = !is_null( $this->getLBInfo( 'master' ) );
+               $trxProf = Profiler::instance()->getTransactionProfiler();
+               $trxProf->recordConnection( $this->mServer, $this->mDBname, 
$isMaster );
        }
 
        /**
diff --git a/includes/profiler/TransactionProfiler.php 
b/includes/profiler/TransactionProfiler.php
index 886bc5a..57d0474 100644
--- a/includes/profiler/TransactionProfiler.php
+++ b/includes/profiler/TransactionProfiler.php
@@ -40,6 +40,80 @@
        /** @var array transaction ID => list of (query name, start time, end 
time) */
        protected $dbTrxMethodTimes = array();
 
+       /** @var array */
+       protected $hits = array(
+               'writes'      => 0,
+               'queries'     => 0,
+               'conns'       => 0,
+               'masterConns' => 0
+       );
+       /** @var array */
+       protected $expect = array(
+               'writes'      => INF,
+               'queries'     => INF,
+               'conns'       => INF,
+               'masterConns' => INF
+       );
+       /** @var array */
+       protected $expectBy = array();
+
+       /**
+        * Set performance expectations
+        *
+        * With conflicting expect, the most specific ones will be used
+        *
+        * @param string $event (writes,queries,conns,mConns)
+        * @param integer $value Maximum count of the event
+        * @param string $fname Caller
+        * @since 1.25
+        */
+       public function setExpectation( $event, $value, $fname ) {
+               $this->expect[$event] = isset( $this->expect[$event] )
+                       ? min( $this->expect[$event], $value )
+                       : $value;
+               if ( $this->expect[$event] == $value ) {
+                       $this->expectBy[$event] = $fname;
+               }
+       }
+
+       /**
+        * Reset performance expectations and hit counters
+        *
+        * Probably only useful in CLI mode
+        *
+        * @since 1.25
+        */
+       public function resetExpectationsAndCounters() {
+               foreach ( $this->hits as &$val ) {
+                       $val = 0;
+               }
+               unset( $val );
+               foreach ( $this->expect as &$val ) {
+                       $val = INF;
+               }
+               unset( $val );
+               $this->expectBy = array();
+       }
+
+       /**
+        * Mark a DB as having been connected to with a new handle
+        *
+        * Note that there can be multiple connections to a single DB.
+        *
+        * @param string $server DB server
+        * @param string $db DB name
+        * @param bool $isMaster
+        */
+       public function recordConnection( $server, $db, $isMaster ) {
+               // Report when too many connections happen...
+               if ( $this->hits['conns']++ == $this->expect['conns'] ) {
+                       $this->reportExpectationViolated( 'conns', "[connect to 
$server ($db)]" );
+               }
+               if ( $isMaster && $this->hits['masterConns']++ == 
$this->expect['masterConns'] ) {
+                       $this->reportExpectationViolated( 'masterConns', 
"[connect to $server ($db)]" );
+               }
+       }
+
        /**
         * Mark a DB as in a transaction with one or more writes pending
         *
@@ -78,6 +152,14 @@
        public function recordQueryCompletion( $query, $sTime, $isWrite = false 
) {
                $eTime = microtime( true );
                $elapsed = ( $eTime - $sTime );
+
+               // Report when too many writes/queries happen...
+               if ( $this->hits['queries']++ == $this->expect['queries'] ) {
+                       $this->reportExpectationViolated( 'queries', $query );
+               }
+               if ( $isWrite && $this->hits['writes']++ == 
$this->expect['writes'] ) {
+                       $this->reportExpectationViolated( 'writes', $query );
+               }
 
                if ( !$this->dbTrxHoldingLocks ) {
                        // Short-circuit
@@ -155,4 +237,15 @@
                unset( $this->dbTrxHoldingLocks[$name] );
                unset( $this->dbTrxMethodTimes[$name] );
        }
+
+       /**
+        * @param string $expect
+        * @param string $query
+        */
+       protected function reportExpectationViolated( $expect, $query ) {
+               $n = $this->expect[$expect];
+               $by = $this->expectBy[$expect];
+               wfDebugLog( 'DBPerformance',
+                       "Expectation ($expect <= $n) by $by not met:\n$query\n" 
. wfBacktrace( true ) );
+       }
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/185342
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic2ae95c33facbb54e062aef2ce67d6182caa044a
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Aaron Schulz <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to