_aFiles[] = unserialize(file_get_contents($sFile)); } return $this; } /** * Run * * @return array */ public function run() { $aResult = array(); foreach ($this->_aFiles as $aTrace) { foreach ($aTrace as $sFunction => $aData) { $bAdd = true; foreach ($this->_aFilter as $sFilter) { if (strpos($sFunction, $sFilter) !== false) { $bAdd = false; break; } } if ($bAdd === true) { if (isset($aResult[$sFunction]) === false) { $aResult[$sFunction] = array(); } $this->_merge($aResult[$sFunction], $aData); } } } $this->_order($aResult); $this->_aResult = $aResult; return $this; } /** * Limit the result * * @param int $iLimit * * @return xhparser */ public function limit($iLimit = 0) { $iLimit = (int) $iLimit; if ($iLimit > 0) { $this->_aResult = array_slice($this->_aResult, 0, $iLimit); } return $this; } /** * Return the result-string * * @return string */ public function get() { $sResult = ''; foreach ($this->_aResult as $sFunction => $aResult) { $sResult .= PHP_EOL . sprintf('Result: %s', $sFunction) . PHP_EOL . "Num\tCalls\t(avg)\t"; $sResult .= str_pad("Wall", 10, " "); $sResult .= str_pad("(avg)", 10, " "); $sResult .= str_pad("CPU", 10, " "); $sResult .= str_pad("(avg)", 10, " "); $sResult .= str_pad("MEM", 10, " "); $sResult .= str_pad("(avg)", 10, " "); $sResult .= PHP_EOL; $sResult .= ($aResult['count'] . "\t"); $sResult .= ($aResult['ct'] . "\t"); $sResult .= (ceil($aResult['ct_avg']) . "\t"); $sResult .= str_pad($aResult['wt'], 10, " "); $sResult .= str_pad(ceil($aResult['wt_avg']), 10, " "); $sResult .= str_pad($aResult['cpu'], 10, " "); $sResult .= str_pad(ceil($aResult['cpu_avg']), 10, " "); $sResult .= str_pad(round($aResult['mu'] / 1024, 2), 10, " "); $sResult .= str_pad(round($aResult['mu_avg'] / 1024, 2), 10, " "); $sResult .= (PHP_EOL); } return $sResult; } /** * Merge data of a function * * @param array $aBase * @param array $aData * * @return xhparser */ protected function _merge(array &$aBase, array $aData) { $aData['count'] = 1; if (empty($aBase) === true) { $aBase = $aData; } else { foreach ($aData as $sKey => $mValue) { $aBase[$sKey] += $mValue; } } foreach ($aData as $sKey => $mValue) { $aBase[$sKey . '_avg'] = ($aBase[$sKey] / $aBase['count']); } return $this; } /** * Order the traces of a file * * @param array $aTrace * * @return xhparser */ protected function _order(&$aTrace) { foreach ($aTrace as $sKey => $aRow) { $aMemory[$sKey] = $aRow[$this->_sOrder]; } array_multisort($aMemory, SORT_DESC, $aTrace); return $this; } /** * Set order by * * @param string $sOrder * * @return xhparser */ public function order($sOrder) { $this->_sOrder = $sOrder; return $this; } /** * Add a filter * * @param string $sFilter * * @return xhparser */ public function filter($sFilter) { $this->_aFilter[] = trim($sFilter); return $this; } } $o = new xhparser(); $aArgs = getopt('f:d:l:o:'); if (isset($aArgs['d']) !== true) { $aArgs['d'] = ini_get('xhprof.output_dir'); } if (isset($aArgs['o']) === true) { $o->order($aArgs['o']); } if (empty($aArgs['f']) !== true) { $aFilter = explode(',', $aArgs['f']); foreach ($aFilter as $sFilter) { $o->filter($sFilter); } } $oIterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(realpath($aArgs['d']))); $aFiles = array(); foreach ($oIterator as $sName => $oFile) { $aFiles[] = $oFile->getPath() . DIRECTORY_SEPARATOR . $oFile->getFilename(); } foreach ($aFiles as $sFile) { $o->load($sFile); } $o->run(); if (empty($aArgs['l']) !== true) { $o->limit($aArgs['l']); } print_r($o->get());