Maintenance script for benchmarking parse operations
[lhc/web/wiklou.git] / maintenance / benchmarks / benchmarkParse.php
1 <?php
2
3 require __DIR__ . '/../Maintenance.php';
4
5 class BenchmarkParse extends Maintenance {
6 /** @var string MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS) */
7 private $templateTimestamp;
8
9 private $idCache = array();
10
11 function __construct() {
12 parent::__construct();
13 $this->addDescription( 'Benchmark parse operation' );
14 $this->addArg( 'title', 'The name of the page to parse' );
15 $this->addOption( 'cold', 'Don\'t repeat the parse operation to warm the cache' );
16 $this->addOption( 'page-time',
17 'Use the version of the page which was current at the given time',
18 false, true );
19 $this->addOption( 'tpl-time',
20 'Use templates which were current at the given time (except that moves and deletes are not handled properly)',
21 false, true );
22 }
23
24 function execute() {
25 global $wgParser;
26
27 if ( $this->hasOption( 'tpl-time' ) ) {
28 $this->templateTimestamp = wfTimestamp( TS_MW, strtotime( $this->getOption( 'tpl-time' ) ) );
29 Hooks::register( 'BeforeParserFetchTemplateAndtitle', array( $this, 'onFetchTemplate' ) );
30 }
31 $title = Title::newFromText( $this->getArg() );
32 if ( !$title ) {
33 $this->error( "Invalid title" );
34 exit( 1 );
35 }
36 if ( $this->hasOption( 'page-time' ) ) {
37 $pageTimestamp = wfTimestamp( TS_MW, strtotime( $this->getOption( 'page-time' ) ) );
38 $id = $this->getRevIdForTime( $title, $pageTimestamp );
39 if ( !$id ) {
40 $this->error( "The page did not exist at that time" );
41 exit( 1 );
42 }
43
44 $revision = Revision::newFromId( $id );
45 } else {
46 $revision = Revision::newFromTitle( $title );
47 }
48 if ( !$revision ) {
49 $this->error( "Unable to load revision, incorrect title?" );
50 exit( 1 );
51 }
52 if ( !$this->hasOption( 'cold' ) ) {
53 $this->runParser( $revision );
54 }
55 $startUsage = getrusage();
56 $startTime = microtime( true );
57 $this->runParser( $revision );
58 $endUsage = getrusage();
59 $endTime = microtime( true );
60
61 printf( "CPU time = %.3f s, wall clock time = %.3f s\n",
62 $endUsage['ru_utime.tv_sec'] + $endUsage['ru_utime.tv_usec'] * 1e-6
63 - $startUsage['ru_utime.tv_sec'] - $startUsage['ru_utime.tv_usec'] * 1e-6,
64 $endTime - $startTime );
65 }
66
67 /**
68 * @param Title $title
69 * @param string $timestamp
70 * @return bool|mixed
71 */
72 function getRevIdForTime( $title, $timestamp ) {
73 $dbr = wfGetDB( DB_SLAVE );
74 $id = $dbr->selectField(
75 array( 'revision', 'page' ),
76 'rev_id',
77 array(
78 'page_namespace' => $title->getNamespace(),
79 'page_title' => $title->getDBkey(),
80 'rev_page=page_id',
81 'rev_timestamp <= ' . $dbr->addQuotes( $timestamp )
82 ),
83 __METHOD__,
84 array( 'ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 1 ) );
85
86 return $id;
87 }
88
89 /**
90 * @param Revision $revision
91 */
92 function runParser( $revision ) {
93 $content = $revision->getContent();
94 $content->getParserOutput( $revision->getTitle(), $revision->getId() );
95 }
96
97 /**
98 * @param Parser $parser
99 * @param Title $title
100 * @param $skip
101 * @param $id
102 * @return bool
103 */
104 function onFetchTemplate( $parser, $title, &$skip, &$id ) {
105 $pdbk = $title->getPrefixedDBkey();
106 if ( !isset( $this->idCache[$pdbk] ) ) {
107 $proposedId = $this->getRevIdForTime( $title, $this->templateTimestamp );
108 $this->idCache[$pdbk] = $proposedId;
109 }
110 if ( $this->idCache[$pdbk] !== false ) {
111 $id = $this->idCache[$pdbk];
112 }
113
114 return true;
115 }
116 }
117
118 $maintClass = 'BenchmarkParse';
119 require RUN_MAINTENANCE_IF_MAIN;