MediaWiki master
mctest.php
Go to the documentation of this file.
1<?php
27
28// @codeCoverageIgnoreStart
29require_once __DIR__ . '/Maintenance.php';
30// @codeCoverageIgnoreEnd
31
38class McTest extends Maintenance {
39 public function __construct() {
40 parent::__construct();
41 $this->addDescription(
42 "Makes several operation requests on every cache server and shows a report.\n" .
43 "This tests both per-key and batched *Multi() methods as well as WRITE_BACKGROUND.\n" .
44 "\"IB\" means \"immediate blocking\" and \"DB\" means \"deferred blocking.\""
45 );
46 $this->addOption( 'cache', 'Use servers from this $wgObjectCaches store', true, true );
47 $this->addOption( 'class', 'Override the store "class" parameter', false, true );
48 $this->addOption( 'i', 'Number of iterations', false, true );
49 $this->addArg( 'server[:port]', 'Cache server to test, with optional port', false );
50 }
51
52 public function execute() {
53 $config = $this->getConfig();
54 $objectCaches = $config->get( MainConfigNames::ObjectCaches );
55
56 $cacheType = $this->getOption( 'cache', $config->get( MainConfigNames::MainCacheType ) );
57 $iterations = $this->getOption( 'i', 100 );
58 $classOverride = $this->getOption( 'class' );
59 $server = $this->getArg( 0 );
60
61 if ( !isset( $objectCaches[$cacheType] ) ) {
62 $this->fatalError( "No configured '$cacheType' cache" );
63 }
64
65 if ( $classOverride !== null ) {
66 if ( !is_subclass_of( $classOverride, BagOStuff::class ) ) {
67 $this->fatalError( "Invalid class '$classOverride' for cache" );
68 }
69 $class = $classOverride;
70 } else {
71 $class = $objectCaches[$cacheType]['class'];
72 }
73
74 if ( $server !== null ) {
75 $servers = [ $server ];
76 } else {
77 // Note that some caches, like apcu, do not have a server list
78 $servers = $objectCaches[$cacheType]['servers'] ?? [ null ];
79 }
80
81 // Use longest server string for output alignment
82 $maxSrvLen = max( array_map( 'strlen', $servers ) );
83
84 $this->output( "Warming up connections to cache servers..." );
86 $cacheByServer = [];
87 foreach ( $servers as $server ) {
88 $conf = $objectCaches[$cacheType];
89 if ( $server !== null ) {
90 $conf['servers'] = [ $server ];
91 $host = $server;
92 } else {
93 $host = 'localhost';
94 }
95 $cacheByServer[$host] = new $class( $conf );
96 $cacheByServer[$host]->get( 'key' );
97 }
98 $this->output( "done\n" );
99 $this->output( "Single and batched operation profiling/test results:\n" );
100
101 $valueByKey = [];
102 for ( $i = 1; $i <= $iterations; $i++ ) {
103 $valueByKey["test$i"] = 'S' . str_pad( (string)$i, 2048 );
104 }
105
106 foreach ( $cacheByServer as $host => $mcc ) {
107 $this->output( str_pad( $host, $maxSrvLen ) . "\n" );
108 $this->benchmarkSingleKeyOps( $mcc, $valueByKey );
109 $this->benchmarkMultiKeyOpsImmediateBlocking( $mcc, $valueByKey );
110 $this->benchmarkMultiKeyOpsDeferredBlocking( $mcc, $valueByKey );
111 }
112 }
113
118 private function benchmarkSingleKeyOps( BagOStuff $mcc, array $valueByKey ) {
119 $add = 0;
120 $set = 0;
121 $incr = 0;
122 $get = 0;
123 $delete = 0;
124
125 $keys = array_keys( $valueByKey );
126 $count = count( $valueByKey );
127
128 // Clear out any old values
129 $mcc->deleteMulti( $keys );
130
131 $time_start = microtime( true );
132 foreach ( $valueByKey as $key => $value ) {
133 if ( $mcc->add( $key, $value ) ) {
134 $add++;
135 }
136 }
137 $addMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
138
139 $time_start = microtime( true );
140 foreach ( $valueByKey as $key => $value ) {
141 if ( $mcc->set( $key, $value ) ) {
142 $set++;
143 }
144 }
145 $setMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
146
147 $time_start = microtime( true );
148 foreach ( $valueByKey as $key => $value ) {
149 if ( $mcc->get( $key ) === $value ) {
150 $get++;
151 }
152 }
153 $getMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
154
155 $time_start = microtime( true );
156 foreach ( $keys as $key ) {
157 if ( $mcc->delete( $key ) ) {
158 $delete++;
159 }
160 }
161 $delMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
162
163 $time_start = microtime( true );
164 foreach ( $keys as $index => $key ) {
165 if ( $mcc->incrWithInit( $key, $mcc::TTL_INDEFINITE, $index ) === $index ) {
166 $incr++;
167 }
168 }
169 $incrMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
170
171 $this->output(
172 " add: $add/$count {$addMs}ms " .
173 "set: $set/$count {$setMs}ms " .
174 "get: $get/$count ({$getMs}ms) " .
175 "delete: $delete/$count ({$delMs}ms) " .
176 "incr: $incr/$count ({$incrMs}ms)\n"
177 );
178 }
179
184 private function benchmarkMultiKeyOpsImmediateBlocking( BagOStuff $mcc, array $valueByKey ) {
185 $keys = array_keys( $valueByKey );
186 $iterations = count( $valueByKey );
187
188 $time_start = microtime( true );
189 $mSetOk = $mcc->setMulti( $valueByKey ) ? '✓' : '✗';
190 $mSetMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
191
192 $time_start = microtime( true );
193 $found = $mcc->getMulti( $keys );
194 $mGetMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
195 $mGetOk = 0;
196 foreach ( $found as $key => $value ) {
197 $mGetOk += ( $value === $valueByKey[$key] );
198 }
199
200 $time_start = microtime( true );
201 $mChangeTTLOk = $mcc->changeTTLMulti( $keys, 3600 ) ? '✓' : '✗';
202 $mChangeTTTMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
203
204 $time_start = microtime( true );
205 $mDelOk = $mcc->deleteMulti( $keys ) ? '✓' : '✗';
206 $mDelMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
207
208 $this->output(
209 " setMulti (IB): $mSetOk {$mSetMs}ms " .
210 "getMulti (IB): $mGetOk/$iterations {$mGetMs}ms " .
211 "changeTTLMulti (IB): $mChangeTTLOk {$mChangeTTTMs}ms " .
212 "deleteMulti (IB): $mDelOk {$mDelMs}ms\n"
213 );
214 }
215
220 private function benchmarkMultiKeyOpsDeferredBlocking( BagOStuff $mcc, array $valueByKey ) {
221 $keys = array_keys( $valueByKey );
222 $iterations = count( $valueByKey );
223 $flags = $mcc::WRITE_BACKGROUND;
224
225 $time_start = microtime( true );
226 $mSetOk = $mcc->setMulti( $valueByKey, 0, $flags ) ? '✓' : '✗';
227 $mSetMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
228
229 $time_start = microtime( true );
230 $found = $mcc->getMulti( $keys );
231 $mGetMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
232 $mGetOk = 0;
233 foreach ( $found as $key => $value ) {
234 $mGetOk += ( $value === $valueByKey[$key] );
235 }
236
237 $time_start = microtime( true );
238 $mChangeTTLOk = $mcc->changeTTLMulti( $keys, 3600, $flags ) ? '✓' : '✗';
239 $mChangeTTTMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
240
241 $time_start = microtime( true );
242 $mDelOk = $mcc->deleteMulti( $keys, $flags ) ? '✓' : '✗';
243 $mDelMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
244
245 $this->output(
246 " setMulti (DB): $mSetOk {$mSetMs}ms " .
247 "getMulti (DB): $mGetOk/$iterations {$mGetMs}ms " .
248 "changeTTLMulti (DB): $mChangeTTLOk {$mChangeTTTMs}ms " .
249 "deleteMulti (DB): $mDelOk {$mDelMs}ms\n"
250 );
251 }
252}
253
254// @codeCoverageIgnoreStart
255$maintClass = McTest::class;
256require_once RUN_MAINTENANCE_IF_MAIN;
257// @codeCoverageIgnoreEnd
Maintenance script that makes several 'set', 'incr' and 'get' requests on every memcached server and ...
Definition mctest.php:38
__construct()
Definition mctest.php:39
execute()
Definition mctest.php:52
A class containing constants representing the names of configuration variables.
Abstract class for any ephemeral data store.
Definition BagOStuff.php:89
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.
getMulti(array $keys, $flags=0)
Get a batch of items.
delete( $key, $flags=0)
Delete an item if it exists.
set( $key, $value, $exptime=0, $flags=0)
Set an item.
deleteMulti(array $keys, $flags=0)
Delete a batch of items.
get( $key, $flags=0)
Get an item.
changeTTLMulti(array $keys, $exptime, $flags=0)
Change the expiration of multiple items.
setMulti(array $valueByKey, $exptime=0, $flags=0)
Set a batch of items.
add( $key, $value, $exptime=0, $flags=0)
Insert an item if it does not already exist.
$maintClass
Definition mctest.php:255