getTraceList()); break; case 'function_list': $dataFile = get('dataFile'); if ($dataFile=='0') { $files = Webgrind_FileHandler::getInstance()->getTraceList(); $dataFile = $files[0]['filename']; } $reader = Webgrind_FileHandler::getInstance()->getTraceReader($dataFile, get('costFormat', Webgrind_Config::$defaultCostformat)); $functions = array(); $shownTotal = 0; $breakdown = array('internal' => 0, 'procedural' => 0, 'class' => 0, 'include' => 0); for ($i=0; $i<$reader->getFunctionCount(); $i++) { $functionInfo = $reader->getFunctionInfo($i); if (false !== strpos($functionInfo['functionName'], 'php::')) { $breakdown['internal'] += $functionInfo['summedSelfCostRaw']; $humanKind = 'internal'; } else if (false !== strpos($functionInfo['functionName'], 'require_once::') || false !== strpos($functionInfo['functionName'], 'require::') || false !== strpos($functionInfo['functionName'], 'include_once::') || false !== strpos($functionInfo['functionName'], 'include::')) { $breakdown['include'] += $functionInfo['summedSelfCostRaw']; $humanKind = 'include'; } else { if (false !== strpos($functionInfo['functionName'], '->') || false !== strpos($functionInfo['functionName'], '::')) { $breakdown['class'] += $functionInfo['summedSelfCostRaw']; $humanKind = 'class'; } else { $breakdown['procedural'] += $functionInfo['summedSelfCostRaw']; $humanKind = 'procedural'; } } if (!(int)get('hideInternals', 0) || strpos($functionInfo['functionName'], 'php::') === false) { $shownTotal += $functionInfo['summedSelfCostRaw']; $functions[$i] = $functionInfo; $functions[$i]['nr'] = $i; $functions[$i]['humanKind'] = $humanKind; } } usort($functions,'costCmp'); $remainingCost = $shownTotal*get('showFraction'); $result['functions'] = array(); foreach ($functions as $function) { $remainingCost -= $function['summedSelfCostRaw']; $function['file'] = urlencode($function['file']); $result['functions'][] = $function; if ($remainingCost<0) break; } $result['summedInvocationCount'] = $reader->getFunctionCount(); $result['summedRunTime'] = $reader->formatCost($reader->getHeader('summary'), 'msec'); $result['dataFile'] = $dataFile; $result['invokeUrl'] = $reader->getHeader('cmd'); $result['runs'] = $reader->getHeader('runs'); $result['breakdown'] = $breakdown; $result['mtime'] = date(Webgrind_Config::$dateFormat,filemtime(Webgrind_Config::xdebugOutputDir().$dataFile)); $creator = preg_replace('/[^0-9\.]/', '', $reader->getHeader('creator')); $result['linkToFunctionLine'] = version_compare($creator, '2.1') > 0; sendJson($result); break; case 'callinfo_list': $reader = Webgrind_FileHandler::getInstance()->getTraceReader(get('file'), get('costFormat', Webgrind_Config::$defaultCostformat)); $functionNr = get('functionNr'); $function = $reader->getFunctionInfo($functionNr); $result = array('calledFrom'=>array(), 'subCalls'=>array()); $foundInvocations = 0; for ($i=0; $i<$function['calledFromInfoCount']; $i++) { $invo = $reader->getCalledFromInfo($functionNr, $i); $foundInvocations += $invo['callCount']; $callerInfo = $reader->getFunctionInfo($invo['functionNr']); $invo['file'] = urlencode($callerInfo['file']); $invo['callerFunctionName'] = $callerInfo['functionName']; $result['calledFrom'][] = $invo; } $result['calledByHost'] = ($foundInvocations<$function['invocationCount']); for ($i=0; $i<$function['subCallInfoCount']; $i++) { $invo = $reader->getSubCallInfo($functionNr, $i); $callInfo = $reader->getFunctionInfo($invo['functionNr']); $invo['file'] = urlencode($function['file']); // Sub call to $callInfo['file'] but from $function['file'] $invo['callerFunctionName'] = $callInfo['functionName']; $result['subCalls'][] = $invo; } sendJson($result); break; case 'fileviewer': $file = get('file'); if ($file && $file!='') { $message = ''; if (!file_exists($file)) { $message = $file.' does not exist.'; } else if (!is_readable($file)) { $message = $file.' is not readable.'; } else if (is_dir($file)) { $message = $file.' is a directory.'; } } else { $message = 'No file to view'; } require 'templates/fileviewer.phtml'; break; case 'function_graph': $dataFile = get('dataFile'); $showFraction = 100 - intval(get('showFraction') * 100); if ($dataFile == '0') { $files = Webgrind_FileHandler::getInstance()->getTraceList(); $dataFile = $files[0]['filename']; } $filename = Webgrind_Config::storageDir().$dataFile.'-'.$showFraction.Webgrind_Config::$preprocessedSuffix.'.'.Webgrind_Config::$graphImageType; if (!file_exists($filename)) { // Add enclosing quotes if needed foreach (array('pythonExecutable', 'dotExecutable') as $exe) { $item =& Webgrind_Config::$$exe; if (strpos($item, ' ') !== false && !preg_match('/^".+"$/', $item)) { $item = '"'.$item.'"'; } } shell_exec(Webgrind_Config::$pythonExecutable.' library/gprof2dot.py -n '.$showFraction .' -f callgrind '.escapeshellarg(Webgrind_Config::xdebugOutputDir().$dataFile).' | ' .Webgrind_Config::$dotExecutable.' -T'.Webgrind_Config::$graphImageType.' -o '.escapeshellarg($filename)); } if (!file_exists($filename)) { $file = $filename; $message = 'Unable to generate '.$file.' via python: '.Webgrind_Config::$pythonExecutable .' and dot: '.Webgrind_Config::$dotExecutable.'. Please update config.php.'; require 'templates/fileviewer.phtml'; break; } if (Webgrind_Config::$graphImageType == 'svg') { header('Content-Type: image/svg+xml'); } else { header('Content-Type: image/'.Webgrind_Config::$graphImageType); } readfile($filename); break; case 'version_info': $response = @file_get_contents('http://jokkedk.github.io/webgrind/webgrindupdate.json?version='.Webgrind_Config::$webgrindVersion); if ($response) { header('Content-type: application/json'); echo $response; } break; case 'clear_files': $files = Webgrind_FileHandler::getInstance()->getTraceList(); if (!$files) { sendJson(array('done' => 'no files found')); break; } $format = array(); foreach ($files as $file) { unlink(Webgrind_Config::xdebugOutputDir().$file['filename']); $format[] = preg_quote($file['filename'], '/'); } $files = preg_grep('/'.implode('|', $format).'/', scandir(Webgrind_Config::storageDir())); foreach ($files as $file) { unlink(Webgrind_Config::storageDir().$file); } sendJson(array('done' => true)); break; default: $welcome = ''; if (!file_exists(Webgrind_Config::storageDir()) || !is_writable(Webgrind_Config::storageDir())) { $welcome .= 'Webgrind $storageDir does not exist or is not writeable: '.Webgrind_Config::storageDir().'
'; } if (!file_exists(Webgrind_Config::xdebugOutputDir()) || !is_readable(Webgrind_Config::xdebugOutputDir())) { $welcome .= 'Webgrind $profilerDir does not exist or is not readable: '.Webgrind_Config::xdebugOutputDir().'
'; } if ($welcome == '') { $welcome = 'Select a cachegrind file above
(looking in '.Webgrind_Config::xdebugOutputDir().' for files matching '.Webgrind_Config::xdebugOutputFormat().')'; } require 'templates/index.phtml'; } } catch (Exception $e) { sendJson(array('error' => $e->getMessage().'
'.$e->getFile().', line '.$e->getLine())); return; } function get($param, $default=false) { return (isset($_GET[$param])? $_GET[$param] : $default); } function costCmp($a, $b) { $a = $a['summedSelfCostRaw']; $b = $b['summedSelfCostRaw']; if ($a == $b) { return 0; } return ($a > $b) ? -1 : 1; } function sendJson($object) { header('Content-type: application/json'); echo json_encode($object); }