-
-
Save jeffery/9681064 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
OCP - Opcache Control Panel (aka Zend Optimizer+ Control Panel for PHP) | |
Author: _ck_, GK, stasilok | |
Version: 0.1.0 | |
Free for any kind of use or modification, I am not responsible for anything, please share your improvements | |
* revision history | |
0.1.0 2013-03-17 added group/sort indicators, replaced "accelerator_" functions with "opcache_" | |
0.0.6 2013-03-16 transition support as Zend renames product and functions for PHP 5.5 (stasilok) | |
0.0.5 2013-03-10 added refresh button (GK) | |
0.0.4 2013-02-18 added file grouping and sorting (click on headers) - code needs cleanup but gets the job done | |
0.0.2 2013-02-14 first public release | |
* known problems/limitations: | |
Unlike APC, the Zend Opcache API | |
- cannot delete/update individual files in the cache manually | |
- cannot change any settings on the fly | |
- cannot determine when a file was first put into the cache | |
- cannot determine how long the cache has been running, only when it was last reset | |
* todo: | |
Extract variables for prefered ordering and better layout instead of just dumping into tables | |
CSS graph of memory use, free, wasted, filecount | |
File list filter | |
*/ | |
// ini_set('display_errors','1'); error_reporting(-1); | |
if ( !empty($_GET['CLEAR']) ) { | |
if ( function_exists('opcache_reset') ) { opcache_reset(); } | |
header( 'Location: '.str_replace('?'.$_SERVER['QUERY_STRING'],'',$_SERVER['REQUEST_URI']) ); | |
exit; | |
} | |
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<title>OCP - Opcache Control Panel</title> | |
<meta name="ROBOTS" content="NOINDEX,NOFOLLOW,NOARCHIVE" /> | |
<style type="text/css"> | |
body {background-color: #fff; color: #000;} | |
body, td, th, h1, h2 {font-family: sans-serif;} | |
pre {margin: 0px; font-family: monospace;} | |
a:link,a:visited {color: #000099; text-decoration: none;} | |
a:hover {text-decoration: underline;} | |
table {border-collapse: collapse;} | |
.center {text-align: center;} | |
.center table { margin-left: auto; margin-right: auto; text-align: left;} | |
.center th { text-align: center !important; } | |
td, th { border: 1px solid #000; font-size: 75%; vertical-align: baseline;} | |
h1 {font-size: 150%;} | |
h2 {font-size: 125%;} | |
.p {text-align: left;} | |
.e {background-color: #ccccff; font-weight: bold; color: #000; width:50%; white-space:nowrap;} | |
.h {background-color: #9999cc; font-weight: bold; color: #000;} | |
.v {background-color: #cccccc; color: #000;} | |
.vr {background-color: #cccccc; text-align: right; color: #000; white-space: nowrap;} | |
.b {font-weight:bold;} | |
img {float: right; border: 0px;} | |
hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000;} | |
.meta, .small {font-size: 75%; } | |
.meta {margin: 10px;} | |
.meta a, th a {padding: 10px; white-space:nowrap; } | |
.buttons {margin:0 0 20px;} | |
.buttons a {margin:0 15px; background-color: #9999cc; color:#fff; text-decoration:none; padding:1px; border:1px solid #000; display:inline-block; width:5em; text-align:center;} | |
</style> | |
</head> | |
<body> | |
<div class="center"> | |
<h1><a href="?">Opcache Control Panel</a></h1> | |
<div class="buttons"> | |
<a href="?ALL=1">Details</a> | |
<a href="?FILES=1&GROUP=2&SORT=3">Files</a> | |
<a href="?CLEAR=1" onclick="return confirm('RESET cache?')">Reset</a> | |
<a href="?" onclick="window.location.reload(true); return false">Refresh</a> | |
</div> | |
<div class="meta"> | |
<a href="http://files.zend.com/help/Zend-Server-6/content/zendoptimizerplus.html">directives guide</a> | | |
<a href="http://files.zend.com/help/Zend-Server-6/content/zend_optimizer+_-_php_api.htm">functions guide</a> | | |
<a href="https://github.com/zend-dev/ZendOptimizerPlus/">Zend source</a> | | |
<a href="https://gist.github.com/ck-on/4959032/?ocp.php">OCP latest</a> | |
</div> | |
<?php | |
if ( !function_exists('opcache_get_status') ) { echo '<h2>Opcache not detected?</h2>'; die; } | |
if ( !empty($_GET['FILES']) ) { echo '<h2>files cached</h2>'; files_display(); echo '</div></body></html>'; exit; } | |
ob_start(); phpinfo(8); $phpinfo = ob_get_contents(); ob_end_clean(); // some info is only available via phpinfo? sadly buffering capture has to be used | |
if ( !preg_match( '/module\_Zend Optimizer\+.+?(\<table[^>]*\>.+?\<\/table\>).+?(\<table[^>]*\>.+?\<\/table\>)/s', $phpinfo, $opcache) ) { } // todo | |
if ( function_exists('opcache_get_configuration') ) { echo '<h2>general</h2>'; $configuration=opcache_get_configuration(); } | |
if ( !empty($configuration['version']['version']) ) { | |
$version=array('Version'=>$configuration['version']['opcache_product_name'].' '.$configuration['version']['version']); | |
print_table($version); | |
} | |
if ( !empty($opcache[1]) ) { echo $opcache[1]; } | |
if ( function_exists('opcache_get_status') && $status=opcache_get_status() ) { | |
if ( !empty($status['cache_full']) ) { $status['memory_usage']['cache_full']=$status['cache_full']; } | |
echo '<h2>memory</h2>'; | |
print_table($status['memory_usage']); | |
if ( !empty($status['opcache_statistics']['last_restart_time']) ) { | |
$status['opcache_statistics']['last_restart']=time_since(time(),$status['opcache_statistics']['last_restart_time']); | |
} | |
unset($status['opcache_statistics']['last_restart_time']); | |
echo '<h2>statistics</h2>'; | |
print_table($status['opcache_statistics']); | |
} | |
if ( empty($_GET['ALL']) ) {exit;} | |
if ( !empty($configuration['blacklist']) ) { echo '<h2>blacklist</h2>'; print_table($configuration['blacklist']); } | |
if ( !empty($opcache[2]) ) { echo '<h2>runtime</h2>'; echo $opcache[2]; } | |
if ( $functions=get_extension_funcs('zend optimizer+') ) { echo '<h2>functions</h2>'; print_table($functions); } | |
echo '</div></body></html>'; | |
exit; | |
function time_since($time,$original) { | |
$text=' ago'; | |
$time = $time - $original; | |
$day = round($time/86400,0); | |
$result = ''; | |
if ( $time < 86400) { | |
if ( $time < 60) { $result = $time.' second'; } | |
elseif ( $time < 3600) { $result = floor($time/60).' minute'; } | |
else { $result = floor($time/3600).' hour'; } | |
} | |
elseif ( $day < 14) { $result = $day.' day'; } | |
elseif ( $day < 56) { $result = floor($day/7).' week'; } | |
elseif ( $day < 672) { $result = floor($day/28).' month'; } | |
else { $result = (intval(2*($day/365))/2).' year'; } | |
if ( intval($result)!=1) {$result.='s';} | |
return $result.$text; | |
} | |
function print_table($array) { | |
if ( empty($array) || !is_array($array) ) {return;} | |
echo '<table border="0" cellpadding="3" width="600">'; | |
foreach ($array as $key=>$value) { | |
echo '<tr>'; | |
if ( !is_numeric($key) ) { | |
$key=ucwords(str_replace('_',' ',$key)); | |
echo '<td class="e">',$key,'</td>'; | |
if ( is_numeric($value) ) { | |
if ( $value>1048576) { $value=round($value/1048576,1).'M'; } | |
elseif ( is_float($value) ) { $value=round($value,1); } | |
} | |
} | |
if ( is_array($value) ) { | |
foreach ($value as $column) { | |
echo '<td class="v">',$column,'</td>'; | |
} | |
echo '</tr>'; | |
} | |
else { echo '<td class="v">',$value,'</td></tr>'; } | |
} | |
echo '</table>'; | |
} | |
function files_display() { | |
$status=opcache_get_status(); | |
if ( empty($status['scripts']) ) {return;} | |
if ( isset($_GET['DUMP']) ) { print_table($status['scripts']); exit;} | |
$time=time(); $sort=0; | |
$nogroup=preg_replace('/\&?GROUP\=[\-0-9]+/','',$_SERVER['REQUEST_URI']); | |
$nosort=preg_replace('/\&?SORT\=[\-0-9]+/','',$_SERVER['REQUEST_URI']); | |
$group=empty($_GET['GROUP'])?0:intval($_GET['GROUP']); if ( $group<0 || $group>9) { $group=1;} | |
$groupset=array_fill(0,9,''); $groupset[$group]=' class="b" '; | |
echo '<div class="meta"> | |
<a ',$groupset[0],'href="',$nogroup,'">ungroup</a> | | |
<a ',$groupset[1],'href="',$nogroup,'&GROUP=1">1</a> | | |
<a ',$groupset[2],'href="',$nogroup,'&GROUP=2">2</a> | | |
<a ',$groupset[3],'href="',$nogroup,'&GROUP=3">3</a> | | |
<a ',$groupset[4],'href="',$nogroup,'&GROUP=4">4</a> | | |
<a ',$groupset[5],'href="',$nogroup,'&GROUP=5">5</a> | |
</div>'; | |
if ( !$group ) { $files =& $status['scripts']; } | |
else { | |
$files=array(); | |
foreach ($status['scripts'] as $data) { | |
if ( preg_match('@^[/]([^/]+[/]){'.$group.'}@',$data['full_path'],$path) ) { | |
if ( empty($files[$path[0]])) { $files[$path[0]]=array('full_path'=>'','files'=>0,'hits'=>0,'memory_consumption'=>0,'last_used_timestamp'=>'','timestamp'=>''); } | |
$files[$path[0]]['full_path']=$path[0]; | |
$files[$path[0]]['files']++; | |
$files[$path[0]]['memory_consumption']+=$data['memory_consumption']; | |
$files[$path[0]]['hits']+=$data['hits']; | |
if ( $data['last_used_timestamp']>$files[$path[0]]['last_used_timestamp']) {$files[$path[0]]['last_used_timestamp']=$data['last_used_timestamp'];} | |
if ( $data['timestamp']>$files[$path[0]]['timestamp']) {$files[$path[0]]['timestamp']=$data['timestamp'];} | |
} | |
} | |
} | |
if ( !empty($_GET['SORT']) ) { | |
$keys=array( | |
'full_path'=>SORT_STRING, | |
'files'=>SORT_NUMERIC, | |
'memory_consumption'=>SORT_NUMERIC, | |
'hits'=>SORT_NUMERIC, | |
'last_used_timestamp'=>SORT_NUMERIC, | |
'timestamp'=>SORT_NUMERIC | |
); | |
$titles=array('','path',$group?'files':'','size','hits','last used','created'); | |
$offsets=array_keys($keys); | |
$key=intval($_GET['SORT']); | |
$direction=$key>0?1:-1; | |
$key=abs($key)-1; | |
$key=isset($offsets[$key])&&!($key==1&&empty($group))?$offsets[$key]:reset($offsets); | |
$sort=array_search($key,$offsets)+1; | |
$sortflip=range(0,7); $sortflip[$sort]=-$direction*$sort; | |
if ( $keys[$key]==SORT_STRING) {$direction=-$direction; } | |
$arrow=array_fill(0,7,''); $arrow[$sort]=$direction>0?' ▼':' ▲'; | |
$direction=$direction>0?SORT_DESC:SORT_ASC; | |
$column=array(); foreach ($files as $data) { $column[]=$data[$key]; } | |
array_multisort($column, $keys[$key], $direction, $files); | |
} | |
echo '<table border="0" cellpadding="3" width="960"> | |
<tr class="h">'; | |
foreach ($titles as $column=>$title) { | |
if ($title) echo '<th><a href="',$nosort,'&SORT=',$sortflip[$column],'">',$title,$arrow[$column],'</a></th>'; | |
} | |
echo ' </tr>'; | |
foreach ($files as $data) { | |
echo '<tr> | |
<td class="v" nowrap>',$data['full_path'],'</td>', | |
($group?'<td class="vr">'.$data['files'].'</td>':''), | |
'<td class="vr">',round($data['memory_consumption']/1024),'K</td>', | |
'<td class="vr">',$data['hits'],'</td>', | |
'<td class="vr">',time_since($time,$data['last_used_timestamp']),'</td>', | |
'<td class="vr">',empty($data['timestamp'])?'':time_since($time,$data['timestamp']),'</td> | |
</tr>'; | |
} | |
echo '</table>'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment