37 parent::__construct();
39 "Makes several operation requests on every cache server and shows a report.\n" .
40 "This tests both per-key and batched *Multi() methods as well as WRITE_BACKGROUND.\n" .
41 "\"IB\" means \"immediate blocking\" and \"DB\" means \"deferred blocking.\""
43 $this->
addOption(
'cache',
'Use servers from this $wgObjectCaches store',
true,
true );
44 $this->
addOption(
'class',
'Override the store "class" parameter',
false,
true );
45 $this->
addOption(
'i',
'Number of iterations',
false,
true );
46 $this->
addArg(
'server[:port]',
'Cache server to test, with optional port',
false );
51 $objectCaches = $config->get( MainConfigNames::ObjectCaches );
53 $cacheType = $this->
getOption(
'cache', $config->get( MainConfigNames::MainCacheType ) );
54 $iterations = $this->
getOption(
'i', 100 );
55 $classOverride = $this->
getOption(
'class' );
56 $server = $this->
getArg( 0 );
58 if ( !isset( $objectCaches[$cacheType] ) ) {
59 $this->
fatalError(
"No configured '$cacheType' cache" );
62 if ( $classOverride !==
null ) {
63 if ( !is_subclass_of( $classOverride, BagOStuff::class ) ) {
64 $this->
fatalError(
"Invalid class '$classOverride' for cache" );
66 $class = $classOverride;
68 $class = $objectCaches[$cacheType][
'class'];
71 if ( $server !==
null ) {
72 $servers = [ $server ];
75 $servers = $objectCaches[$cacheType][
'servers'] ?? [ null ];
79 $maxSrvLen = max( array_map(
'strlen', $servers ) );
81 $this->
output(
"Warming up connections to cache servers..." );
84 foreach ( $servers as $server ) {
85 $conf = $objectCaches[$cacheType];
86 if ( $server !==
null ) {
87 $conf[
'servers'] = [ $server ];
92 $cacheByServer[$host] =
new $class( $conf );
93 $cacheByServer[$host]->get(
'key' );
96 $this->
output(
"Single and batched operation profiling/test results:\n" );
99 for ( $i = 1; $i <= $iterations; $i++ ) {
100 $valueByKey[
"test$i"] =
'S' . str_pad( (
string)$i, 2048 );
103 foreach ( $cacheByServer as $host => $mcc ) {
104 $this->
output( str_pad( $host, $maxSrvLen ) .
"\n" );
105 $this->benchmarkSingleKeyOps( $mcc, $valueByKey );
106 $this->benchmarkMultiKeyOpsImmediateBlocking( $mcc, $valueByKey );
107 $this->benchmarkMultiKeyOpsDeferredBlocking( $mcc, $valueByKey );
115 private function benchmarkSingleKeyOps(
BagOStuff $mcc, array $valueByKey ) {
122 $keys = array_keys( $valueByKey );
123 $count = count( $valueByKey );
128 $time_start = microtime(
true );
129 foreach ( $valueByKey as $key => $value ) {
130 if ( $mcc->
add( $key, $value ) ) {
134 $addMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
136 $time_start = microtime(
true );
137 foreach ( $valueByKey as $key => $value ) {
138 if ( $mcc->
set( $key, $value ) ) {
142 $setMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
144 $time_start = microtime(
true );
145 foreach ( $valueByKey as $key => $value ) {
146 if ( $mcc->
get( $key ) === $value ) {
150 $getMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
152 $time_start = microtime(
true );
153 foreach ( $keys as $key ) {
154 if ( $mcc->
delete( $key ) ) {
158 $delMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
160 $time_start = microtime(
true );
161 foreach ( $keys as $index => $key ) {
162 if ( $mcc->
incrWithInit( $key, $mcc::TTL_INDEFINITE, $index ) === $index ) {
166 $incrMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
169 " add: $add/$count {$addMs}ms " .
170 "set: $set/$count {$setMs}ms " .
171 "get: $get/$count ({$getMs}ms) " .
172 "delete: $delete/$count ({$delMs}ms) " .
173 "incr: $incr/$count ({$incrMs}ms)\n"
181 private function benchmarkMultiKeyOpsImmediateBlocking(
BagOStuff $mcc, array $valueByKey ) {
182 $keys = array_keys( $valueByKey );
183 $iterations = count( $valueByKey );
185 $time_start = microtime(
true );
186 $mSetOk = $mcc->
setMulti( $valueByKey ) ?
'✓' :
'✗';
187 $mSetMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
189 $time_start = microtime(
true );
191 $mGetMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
193 foreach ( $found as $key => $value ) {
194 $mGetOk += ( $value === $valueByKey[$key] );
197 $time_start = microtime(
true );
199 $mChangeTTTMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
201 $time_start = microtime(
true );
203 $mDelMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
206 " setMulti (IB): $mSetOk {$mSetMs}ms " .
207 "getMulti (IB): $mGetOk/$iterations {$mGetMs}ms " .
208 "changeTTLMulti (IB): $mChangeTTLOk {$mChangeTTTMs}ms " .
209 "deleteMulti (IB): $mDelOk {$mDelMs}ms\n"
217 private function benchmarkMultiKeyOpsDeferredBlocking(
BagOStuff $mcc, array $valueByKey ) {
218 $keys = array_keys( $valueByKey );
219 $iterations = count( $valueByKey );
220 $flags = $mcc::WRITE_BACKGROUND;
222 $time_start = microtime(
true );
223 $mSetOk = $mcc->
setMulti( $valueByKey, 0, $flags ) ?
'✓' :
'✗';
224 $mSetMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
226 $time_start = microtime(
true );
228 $mGetMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
230 foreach ( $found as $key => $value ) {
231 $mGetOk += ( $value === $valueByKey[$key] );
234 $time_start = microtime(
true );
235 $mChangeTTLOk = $mcc->
changeTTLMulti( $keys, 3600, $flags ) ?
'✓' :
'✗';
236 $mChangeTTTMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
238 $time_start = microtime(
true );
239 $mDelOk = $mcc->
deleteMulti( $keys, $flags ) ?
'✓' :
'✗';
240 $mDelMs = intval( 1e3 * ( microtime(
true ) - $time_start ) );
243 " setMulti (DB): $mSetOk {$mSetMs}ms " .
244 "getMulti (DB): $mGetOk/$iterations {$mGetMs}ms " .
245 "changeTTLMulti (DB): $mChangeTTLOk {$mChangeTTTMs}ms " .
246 "deleteMulti (DB): $mDelOk {$mDelMs}ms\n"
add( $key, $value, $exptime=0, $flags=0)
Insert an item if it does not already exist.
incrWithInit( $key, $exptime, $step=1, $init=null, $flags=0)
Increase the value of the given key (no TTL change) if it exists or create it otherwise.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
addArg( $arg, $description, $required=true, $multi=false)
Add some args that are needed.
output( $out, $channel=null)
Throw some output to the user.
getArg( $argId=0, $default=null)
Get an argument.
addDescription( $text)
Set the description text.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.