X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=maintenance%2Fmctest.php;h=9548d6b688f127c08a9498b46666e25a8f99e3be;hb=cad882954a084a87bae1f5026d5f30cef4d73ac5;hp=c976bd7048258652d394cb9991045f65244ed8c6;hpb=220bda9175a18458449e9d754fb48830c1f76f25;p=lhc%2Fweb%2Fwiklou.git diff --git a/maintenance/mctest.php b/maintenance/mctest.php index c976bd7048..9548d6b688 100644 --- a/maintenance/mctest.php +++ b/maintenance/mctest.php @@ -37,12 +37,15 @@ class McTest extends Maintenance { . " memcached server and shows a report" ); $this->addOption( 'i', 'Number of iterations', false, true ); $this->addOption( 'cache', 'Use servers from this $wgObjectCaches store', false, true ); + $this->addOption( 'driver', 'Either "php" or "pecl"', false, true ); $this->addArg( 'server[:port]', 'Memcached server to test, with optional port', false ); } public function execute() { global $wgMainCacheType, $wgMemCachedTimeout, $wgObjectCaches; + $memcachedTypes = [ CACHE_MEMCACHED, 'memcached-php', 'memcached-pecl' ]; + $cache = $this->getOption( 'cache' ); $iterations = $this->getOption( 'i', 100 ); if ( $cache ) { @@ -50,9 +53,9 @@ class McTest extends Maintenance { $this->fatalError( "MediaWiki isn't configured with a cache named '$cache'" ); } $servers = $wgObjectCaches[$cache]['servers']; - } elseif ( $this->hasArg() ) { - $servers = [ $this->getArg() ]; - } elseif ( $wgMainCacheType === CACHE_MEMCACHED ) { + } elseif ( $this->hasArg( 0 ) ) { + $servers = [ $this->getArg( 0 ) ]; + } elseif ( in_array( $wgMainCacheType, $memcachedTypes, true ) ) { global $wgMemCachedServers; $servers = $wgMemCachedServers; } elseif ( isset( $wgObjectCaches[$wgMainCacheType]['servers'] ) ) { @@ -64,41 +67,177 @@ class McTest extends Maintenance { # find out the longest server string to nicely align output later on $maxSrvLen = $servers ? max( array_map( 'strlen', $servers ) ) : 0; + $type = $this->getOption( 'driver', 'php' ); + if ( $type === 'php' ) { + $class = MemcachedPhpBagOStuff::class; + } elseif ( $type === 'pecl' ) { + $class = MemcachedPeclBagOStuff::class; + } else { + $this->fatalError( "Invalid driver type '$type'" ); + } + foreach ( $servers as $server ) { - $this->output( - str_pad( $server, $maxSrvLen ), - $server # output channel - ); + $this->output( str_pad( $server, $maxSrvLen ) . "\n" ); - $mcc = new MemcachedClient( [ - 'persistant' => true, + /** @var BagOStuff $mcc */ + $mcc = new $class( [ + 'servers' => [ $server ], + 'persistent' => true, 'timeout' => $wgMemCachedTimeout ] ); - $mcc->set_servers( [ $server ] ); - $set = 0; - $incr = 0; - $get = 0; - $time_start = microtime( true ); - for ( $i = 1; $i <= $iterations; $i++ ) { - if ( $mcc->set( "test$i", $i ) ) { - $set++; - } + + $this->benchmarkSingleKeyOps( $mcc, $iterations ); + $this->benchmarkMultiKeyOpsImmediateBlocking( $mcc, $iterations ); + $this->benchmarkMultiKeyOpsDeferredBlocking( $mcc, $iterations ); + } + } + + /** + * @param BagOStuff $mcc + * @param int $iterations + */ + private function benchmarkSingleKeyOps( $mcc, $iterations ) { + $add = 0; + $set = 0; + $incr = 0; + $get = 0; + $delete = 0; + + $keys = []; + for ( $i = 1; $i <= $iterations; $i++ ) { + $keys[] = "test$i"; + } + + // Clear out any old values + $mcc->deleteMulti( $keys ); + + $time_start = microtime( true ); + foreach ( $keys as $key ) { + if ( $mcc->add( $key, $i ) ) { + $add++; + } + } + $addMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $time_start = microtime( true ); + foreach ( $keys as $key ) { + if ( $mcc->set( $key, $i ) ) { + $set++; } - for ( $i = 1; $i <= $iterations; $i++ ) { - if ( !is_null( $mcc->incr( "test$i", $i ) ) ) { - $incr++; - } + } + $setMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $time_start = microtime( true ); + foreach ( $keys as $key ) { + if ( !is_null( $mcc->incr( $key, $i ) ) ) { + $incr++; + } + } + $incrMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $time_start = microtime( true ); + foreach ( $keys as $key ) { + $value = $mcc->get( $key ); + if ( $value == $i * 2 ) { + $get++; } - for ( $i = 1; $i <= $iterations; $i++ ) { - $value = $mcc->get( "test$i" ); - if ( $value == $i * 2 ) { - $get++; - } + } + $getMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $time_start = microtime( true ); + foreach ( $keys as $key ) { + if ( $mcc->delete( $key ) ) { + $delete++; } - $exectime = microtime( true ) - $time_start; + } + $delMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $this->output( + " add: $add/$iterations {$addMs}ms " . + "set: $set/$iterations {$setMs}ms " . + "incr: $incr/$iterations {$incrMs}ms " . + "get: $get/$iterations ({$getMs}ms) " . + "delete: $delete/$iterations ({$delMs}ms)\n" + ); + } + + /** + * @param BagOStuff $mcc + * @param int $iterations + */ + private function benchmarkMultiKeyOpsImmediateBlocking( $mcc, $iterations ) { + $keysByValue = []; + for ( $i = 1; $i <= $iterations; $i++ ) { + $keysByValue["test$i"] = 'S' . str_pad( $i, 2048 ); + } + $keyList = array_keys( $keysByValue ); + + $time_start = microtime( true ); + $mSetOk = $mcc->setMulti( $keysByValue ) ? 'S' : 'F'; + $mSetMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $time_start = microtime( true ); + $found = $mcc->getMulti( $keyList ); + $mGetMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + $mGetOk = 0; + foreach ( $found as $key => $value ) { + $mGetOk += ( $value === $keysByValue[$key] ); + } - $this->output( " set: $set incr: $incr get: $get time: $exectime", $server ); + $time_start = microtime( true ); + $mChangeTTLOk = $mcc->changeTTLMulti( $keyList, 3600 ) ? 'S' : 'F'; + $mChangeTTTMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $time_start = microtime( true ); + $mDelOk = $mcc->deleteMulti( $keyList ) ? 'S' : 'F'; + $mDelMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $this->output( + " setMulti (IB): $mSetOk {$mSetMs}ms " . + "getMulti (IB): $mGetOk/$iterations {$mGetMs}ms " . + "changeTTLMulti (IB): $mChangeTTLOk {$mChangeTTTMs}ms " . + "deleteMulti (IB): $mDelOk {$mDelMs}ms\n" + ); + } + + /** + * @param BagOStuff $mcc + * @param int $iterations + */ + private function benchmarkMultiKeyOpsDeferredBlocking( $mcc, $iterations ) { + $flags = $mcc::WRITE_BACKGROUND; + $keysByValue = []; + for ( $i = 1; $i <= $iterations; $i++ ) { + $keysByValue["test$i"] = 'A' . str_pad( $i, 2048 ); + } + $keyList = array_keys( $keysByValue ); + + $time_start = microtime( true ); + $mSetOk = $mcc->setMulti( $keysByValue, 0, $flags ) ? 'S' : 'F'; + $mSetMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $time_start = microtime( true ); + $found = $mcc->getMulti( $keyList ); + $mGetMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + $mGetOk = 0; + foreach ( $found as $key => $value ) { + $mGetOk += ( $value === $keysByValue[$key] ); } + + $time_start = microtime( true ); + $mChangeTTLOk = $mcc->changeTTLMulti( $keyList, 3600, $flags ) ? 'S' : 'F'; + $mChangeTTTMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $time_start = microtime( true ); + $mDelOk = $mcc->deleteMulti( $keyList, $flags ) ? 'S' : 'F'; + $mDelMs = intval( 1e3 * ( microtime( true ) - $time_start ) ); + + $this->output( + " setMulti (DB): $mSetOk {$mSetMs}ms " . + "getMulti (DB): $mGetOk/$iterations {$mGetMs}ms " . + "changeTTLMulti (DB): $mChangeTTLOk {$mChangeTTTMs}ms " . + "deleteMulti (DB): $mDelOk {$mDelMs}ms\n" + ); } }