X-Git-Url: https://scripts.mit.edu/gitweb/autoinstallsdev/mediawiki.git/blobdiff_plain/19e297c21b10b1b8a3acad5e73fc71dcb35db44a..6932310fd58ebef145fa01eb76edf7150284d8ea:/includes/libs/Timing.php diff --git a/includes/libs/Timing.php b/includes/libs/Timing.php new file mode 100644 index 00000000..57c253d5 --- /dev/null +++ b/includes/libs/Timing.php @@ -0,0 +1,195 @@ +clearMarks(); + $this->setLogger( isset( $params['logger'] ) ? $params['logger'] : new NullLogger() ); + } + + /** + * Sets a logger instance on the object. + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger( LoggerInterface $logger ) { + $this->logger = $logger; + } + + /** + * Store a timestamp with the associated name (a "mark") + * + * @param string $markName The name associated with the timestamp. + * If there already exists an entry by that name, it is overwritten. + * @return array The mark that has been created. + */ + public function mark( $markName ) { + $this->entries[$markName] = [ + 'name' => $markName, + 'entryType' => 'mark', + 'startTime' => microtime( true ), + 'duration' => 0, + ]; + return $this->entries[$markName]; + } + + /** + * @param string $markName The name of the mark that should + * be cleared. If not specified, all marks will be cleared. + */ + public function clearMarks( $markName = null ) { + if ( $markName !== null ) { + unset( $this->entries[$markName] ); + } else { + $this->entries = [ + 'requestStart' => [ + 'name' => 'requestStart', + 'entryType' => 'mark', + 'startTime' => isset( $_SERVER['REQUEST_TIME_FLOAT'] ) + ? $_SERVER['REQUEST_TIME_FLOAT'] + : $_SERVER['REQUEST_TIME'], + 'duration' => 0, + ], + ]; + } + } + + /** + * This method stores the duration between two marks along with + * the associated name (a "measure"). + * + * If neither the startMark nor the endMark argument is specified, + * measure() will store the duration from $_SERVER['REQUEST_TIME_FLOAT'] to + * the current time. + * If the startMark argument is specified, but the endMark argument is not + * specified, measure() will store the duration from the most recent + * occurrence of the start mark to the current time. + * If both the startMark and endMark arguments are specified, measure() + * will store the duration from the most recent occurrence of the start + * mark to the most recent occurrence of the end mark. + * + * @param string $measureName + * @param string $startMark + * @param string $endMark + * @return array|bool The measure that has been created, or false if either + * the start mark or the end mark do not exist. + */ + public function measure( $measureName, $startMark = 'requestStart', $endMark = null ) { + $start = $this->getEntryByName( $startMark ); + if ( $start === null ) { + $this->logger->error( __METHOD__ . ": The mark '$startMark' does not exist" ); + return false; + } + $startTime = $start['startTime']; + + if ( $endMark ) { + $end = $this->getEntryByName( $endMark ); + if ( $end === null ) { + $this->logger->error( __METHOD__ . ": The mark '$endMark' does not exist" ); + return false; + } + $endTime = $end['startTime']; + } else { + $endTime = microtime( true ); + } + + $this->entries[$measureName] = [ + 'name' => $measureName, + 'entryType' => 'measure', + 'startTime' => $startTime, + 'duration' => $endTime - $startTime, + ]; + + return $this->entries[$measureName]; + } + + /** + * Sort entries in chronological order with respect to startTime. + */ + private function sortEntries() { + uasort( $this->entries, function ( $a, $b ) { + return 10000 * ( $a['startTime'] - $b['startTime'] ); + } ); + } + + /** + * @return array[] All entries in chronological order. + */ + public function getEntries() { + $this->sortEntries(); + return $this->entries; + } + + /** + * @param string $entryType + * @return array[] Entries (in chronological order) that have the same value + * for the entryType attribute as the $entryType parameter. + */ + public function getEntriesByType( $entryType ) { + $this->sortEntries(); + $entries = []; + foreach ( $this->entries as $entry ) { + if ( $entry['entryType'] === $entryType ) { + $entries[] = $entry; + } + } + return $entries; + } + + /** + * @param string $name + * @return array|null Entry named $name or null if it does not exist. + */ + public function getEntryByName( $name ) { + return isset( $this->entries[$name] ) ? $this->entries[$name] : null; + } +}