MediaWiki
REL1_24
|
00001 <?php 00025 require __DIR__ . '/../Maintenance.php'; 00026 00033 class BenchmarkParse extends Maintenance { 00035 private $templateTimestamp = null; 00036 00038 private $idCache = array(); 00039 00040 function __construct() { 00041 parent::__construct(); 00042 $this->addDescription( 'Benchmark parse operation' ); 00043 $this->addArg( 'title', 'The name of the page to parse' ); 00044 $this->addOption( 'warmup', 'Repeat the parse operation this number of times to warm the cache', 00045 false, true ); 00046 $this->addOption( 'loops', 'Number of times to repeat parse operation post-warmup', 00047 false, true ); 00048 $this->addOption( 'page-time', 00049 'Use the version of the page which was current at the given time', 00050 false, true ); 00051 $this->addOption( 'tpl-time', 00052 'Use templates which were current at the given time (except that moves and ' . 00053 'deletes are not handled properly)', 00054 false, true ); 00055 } 00056 00057 function execute() { 00058 if ( $this->hasOption( 'tpl-time' ) ) { 00059 $this->templateTimestamp = wfTimestamp( TS_MW, strtotime( $this->getOption( 'tpl-time' ) ) ); 00060 Hooks::register( 'BeforeParserFetchTemplateAndtitle', array( $this, 'onFetchTemplate' ) ); 00061 } 00062 00063 $title = Title::newFromText( $this->getArg() ); 00064 if ( !$title ) { 00065 $this->error( "Invalid title" ); 00066 exit( 1 ); 00067 } 00068 00069 if ( $this->hasOption( 'page-time' ) ) { 00070 $pageTimestamp = wfTimestamp( TS_MW, strtotime( $this->getOption( 'page-time' ) ) ); 00071 $id = $this->getRevIdForTime( $title, $pageTimestamp ); 00072 if ( !$id ) { 00073 $this->error( "The page did not exist at that time" ); 00074 exit( 1 ); 00075 } 00076 00077 $revision = Revision::newFromId( $id ); 00078 } else { 00079 $revision = Revision::newFromTitle( $title ); 00080 } 00081 00082 if ( !$revision ) { 00083 $this->error( "Unable to load revision, incorrect title?" ); 00084 exit( 1 ); 00085 } 00086 00087 $warmup = $this->getOption( 'warmup', 1 ); 00088 for ( $i = 0; $i < $warmup; $i++ ) { 00089 $this->runParser( $revision ); 00090 } 00091 00092 $loops = $this->getOption( 'loops', 1 ); 00093 if ( $loops < 1 ) { 00094 $this->error( 'Invalid number of loops specified', true ); 00095 } 00096 $startUsage = getrusage(); 00097 $startTime = microtime( true ); 00098 for ( $i = 0; $i < $loops; $i++ ) { 00099 $this->runParser( $revision ); 00100 } 00101 $endUsage = getrusage(); 00102 $endTime = microtime( true ); 00103 00104 printf( "CPU time = %.3f s, wall clock time = %.3f s\n", 00105 // CPU time 00106 ( $endUsage['ru_utime.tv_sec'] + $endUsage['ru_utime.tv_usec'] * 1e-6 00107 - $startUsage['ru_utime.tv_sec'] - $startUsage['ru_utime.tv_usec'] * 1e-6 ) / $loops, 00108 // Wall clock time 00109 ( $endTime - $startTime ) / $loops 00110 ); 00111 } 00112 00120 function getRevIdForTime( Title $title, $timestamp ) { 00121 $dbr = wfGetDB( DB_SLAVE ); 00122 00123 $id = $dbr->selectField( 00124 array( 'revision', 'page' ), 00125 'rev_id', 00126 array( 00127 'page_namespace' => $title->getNamespace(), 00128 'page_title' => $title->getDBkey(), 00129 'rev_timestamp <= ' . $dbr->addQuotes( $timestamp ) 00130 ), 00131 __METHOD__, 00132 array( 'ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 1 ), 00133 array( 'revision' => array( 'INNER JOIN', 'rev_page=page_id' ) ) 00134 ); 00135 00136 return $id; 00137 } 00138 00144 function runParser( Revision $revision ) { 00145 $content = $revision->getContent(); 00146 $content->getParserOutput( $revision->getTitle(), $revision->getId() ); 00147 } 00148 00159 function onFetchTemplate( Parser $parser, Title $title, &$skip, &$id ) { 00160 $pdbk = $title->getPrefixedDBkey(); 00161 if ( !isset( $this->idCache[$pdbk] ) ) { 00162 $proposedId = $this->getRevIdForTime( $title, $this->templateTimestamp ); 00163 $this->idCache[$pdbk] = $proposedId; 00164 } 00165 if ( $this->idCache[$pdbk] !== false ) { 00166 $id = $this->idCache[$pdbk]; 00167 } 00168 00169 return true; 00170 } 00171 } 00172 00173 $maintClass = 'BenchmarkParse'; 00174 require RUN_MAINTENANCE_IF_MAIN;