MediaWiki  REL1_24
benchmarkParse.php
Go to the documentation of this file.
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;