[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Benchmark script for parse operations 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * http://www.gnu.org/copyleft/gpl.html 19 * 20 * @file 21 * @author Tim Starling <[email protected]> 22 * @ingroup Benchmark 23 */ 24 25 require __DIR__ . '/../Maintenance.php'; 26 27 /** 28 * Maintenance script to benchmark how long it takes to parse a given title at an optionally 29 * specified timestamp 30 * 31 * @since 1.23 32 */ 33 class BenchmarkParse extends Maintenance { 34 /** @var string MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS) */ 35 private $templateTimestamp = null; 36 37 /** @var array Cache that maps a Title DB key to revision ID for the requested timestamp */ 38 private $idCache = array(); 39 40 function __construct() { 41 parent::__construct(); 42 $this->addDescription( 'Benchmark parse operation' ); 43 $this->addArg( 'title', 'The name of the page to parse' ); 44 $this->addOption( 'warmup', 'Repeat the parse operation this number of times to warm the cache', 45 false, true ); 46 $this->addOption( 'loops', 'Number of times to repeat parse operation post-warmup', 47 false, true ); 48 $this->addOption( 'page-time', 49 'Use the version of the page which was current at the given time', 50 false, true ); 51 $this->addOption( 'tpl-time', 52 'Use templates which were current at the given time (except that moves and ' . 53 'deletes are not handled properly)', 54 false, true ); 55 } 56 57 function execute() { 58 if ( $this->hasOption( 'tpl-time' ) ) { 59 $this->templateTimestamp = wfTimestamp( TS_MW, strtotime( $this->getOption( 'tpl-time' ) ) ); 60 Hooks::register( 'BeforeParserFetchTemplateAndtitle', array( $this, 'onFetchTemplate' ) ); 61 } 62 63 $title = Title::newFromText( $this->getArg() ); 64 if ( !$title ) { 65 $this->error( "Invalid title" ); 66 exit( 1 ); 67 } 68 69 if ( $this->hasOption( 'page-time' ) ) { 70 $pageTimestamp = wfTimestamp( TS_MW, strtotime( $this->getOption( 'page-time' ) ) ); 71 $id = $this->getRevIdForTime( $title, $pageTimestamp ); 72 if ( !$id ) { 73 $this->error( "The page did not exist at that time" ); 74 exit( 1 ); 75 } 76 77 $revision = Revision::newFromId( $id ); 78 } else { 79 $revision = Revision::newFromTitle( $title ); 80 } 81 82 if ( !$revision ) { 83 $this->error( "Unable to load revision, incorrect title?" ); 84 exit( 1 ); 85 } 86 87 $warmup = $this->getOption( 'warmup', 1 ); 88 for ( $i = 0; $i < $warmup; $i++ ) { 89 $this->runParser( $revision ); 90 } 91 92 $loops = $this->getOption( 'loops', 1 ); 93 if ( $loops < 1 ) { 94 $this->error( 'Invalid number of loops specified', true ); 95 } 96 $startUsage = getrusage(); 97 $startTime = microtime( true ); 98 for ( $i = 0; $i < $loops; $i++ ) { 99 $this->runParser( $revision ); 100 } 101 $endUsage = getrusage(); 102 $endTime = microtime( true ); 103 104 printf( "CPU time = %.3f s, wall clock time = %.3f s\n", 105 // CPU time 106 ( $endUsage['ru_utime.tv_sec'] + $endUsage['ru_utime.tv_usec'] * 1e-6 107 - $startUsage['ru_utime.tv_sec'] - $startUsage['ru_utime.tv_usec'] * 1e-6 ) / $loops, 108 // Wall clock time 109 ( $endTime - $startTime ) / $loops 110 ); 111 } 112 113 /** 114 * Fetch the ID of the revision of a Title that occurred 115 * 116 * @param Title $title 117 * @param string $timestamp 118 * @return bool|string Revision ID, or false if not found or error 119 */ 120 function getRevIdForTime( Title $title, $timestamp ) { 121 $dbr = wfGetDB( DB_SLAVE ); 122 123 $id = $dbr->selectField( 124 array( 'revision', 'page' ), 125 'rev_id', 126 array( 127 'page_namespace' => $title->getNamespace(), 128 'page_title' => $title->getDBkey(), 129 'rev_timestamp <= ' . $dbr->addQuotes( $timestamp ) 130 ), 131 __METHOD__, 132 array( 'ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 1 ), 133 array( 'revision' => array( 'INNER JOIN', 'rev_page=page_id' ) ) 134 ); 135 136 return $id; 137 } 138 139 /** 140 * Parse the text from a given Revision 141 * 142 * @param Revision $revision 143 */ 144 function runParser( Revision $revision ) { 145 $content = $revision->getContent(); 146 $content->getParserOutput( $revision->getTitle(), $revision->getId() ); 147 } 148 149 /** 150 * Hook into the parser's revision ID fetcher. Make sure that the parser only 151 * uses revisions around the specified timestamp. 152 * 153 * @param Parser $parser 154 * @param Title $title 155 * @param bool &$skip 156 * @param string|bool &$id 157 * @return bool 158 */ 159 function onFetchTemplate( Parser $parser, Title $title, &$skip, &$id ) { 160 $pdbk = $title->getPrefixedDBkey(); 161 if ( !isset( $this->idCache[$pdbk] ) ) { 162 $proposedId = $this->getRevIdForTime( $title, $this->templateTimestamp ); 163 $this->idCache[$pdbk] = $proposedId; 164 } 165 if ( $this->idCache[$pdbk] !== false ) { 166 $id = $this->idCache[$pdbk]; 167 } 168 169 return true; 170 } 171 } 172 173 $maintClass = 'BenchmarkParse'; 174 require RUN_MAINTENANCE_IF_MAIN;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |