opcache,php自身集成的缓存功能。由于我的系统是ubuntu server系统,所以在安装的时候很简单,直接apt-get install 方式安装的php,而且安装的是php5.5的版本,所以系统是自带opcache的,不需要我们再重新安装。
接下来要配置一下opcache
sudo vi /etc/php5/fpm/conf.d ; configuration for php ZendOpcache module ; priority=05 ;zend_extension=opcache.so opcache.enable=1 opcache.save_comments=1 opcache.memory_consumption=512 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.revalidate_freq=60 opcache.fast_shutdown=1 opcache.enable_cli=1 opcode.caching=1 opcache.force_restart_timeout=3600 opcache.optimization_level=0xffffffff opcache.optimization=1 opcache.use_cwd=0 opcache.revalidate_path=0 opcache.enable_file_override=0
然后修改php.ini文件,在最后添加一行zend_extension=opcache.so
重启php-fpm或者是nginx,我们可以看到在phpinfo的界面出现了zend opcache的配置信息
好了,到这里我们的opcache已经开始启用了。当然,在上面配置中,可以在php.ini中不加最后一行内容,但是在opcache的配置文件中要把注释去掉,也可以。
现在看起来还是很别扭,我们可以通过直观的图表形式展现出来
好吧,没发过附件,无法上传,好像格式不对,直接上代码吧,网上也有很多的,可以自行百度。
op.php
<?php /** * OPcache GUI * * A simple but effective single-file GUI for the OPcache PHP extension. * * @author Andrew Collington, andy@amnuts.com * @license MIT, http://acollington.mit-license.org/ */ if (!function_exists('opcache_get_status')) { die('The Zend OPcache extension does not appear to be installed'); } $settings = array( 'compress_path_threshold' => 2, 'used_memory_percentage_high_threshold' => 80, 'used_memory_percentage_mid_threshold' => 60, 'allow_invalidate' => true ); $validPages = array('overview', 'files', 'reset', 'invalidate'); $page = (empty($_GET['page']) || !in_array($_GET['page'], $validPages) ? 'overview' : strtolower($_GET['page']) ); if ($page == 'reset') { opcache_reset(); header('Location: ?page=overview'); exit; } if ($page == 'invalidate') { $file = (isset($_GET['file']) ? trim($_GET['file']) : null); if (!$settings['allow_invalidate'] || !function_exists('opcache_invalidate') || empty($file)) { header('Location: ?page=files&error=1'); exit; } $success = (int)opcache_invalidate(urldecode($file), true); header("Location: ?page=files&success={$success}"); exit; } $opcache_config = opcache_get_configuration(); $opcache_status = opcache_get_status(); $opcache_funcs = get_extension_funcs('Zend OPcache'); if (!empty($opcache_status['scripts'])) { uasort($opcache_status['scripts'], function($a, $b) { return $a['hits'] < $b['hits']; }); } function memsize($size, $precision = 3, $space = false) { $i = 0; $val = array(' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'); while (($size / 1024) > 1) { $size /= 1024; ++$i; } return sprintf("%.{$precision}f%s%s", $size, (($space && $i) ? ' ' : ''), $val[$i]); } function rc($at = null) { static $i = 0; if ($at !== null) { $i = $at; } else { echo (++$i % 2 ? 'even' : 'odd'); } } $data = array_merge( $opcache_status['memory_usage'], $opcache_status['opcache_statistics'], array( 'total_memory_size' => memsize($opcache_config['directives']['opcache.memory_consumption']), 'used_memory_percentage' => round(100 * ( ($opcache_status['memory_usage']['used_memory'] + $opcache_status['memory_usage']['wasted_memory']) / $opcache_config['directives']['opcache.memory_consumption'])), 'hit_rate_percentage' => round($opcache_status['opcache_statistics']['opcache_hit_rate']), 'wasted_percentage' => round($opcache_status['memory_usage']['current_wasted_percentage'], 2), 'used_memory_size' => memsize($opcache_status['memory_usage']['used_memory']), 'free_memory_size' => memsize($opcache_status['memory_usage']['free_memory']), 'wasted_memory_size' => memsize($opcache_status['memory_usage']['wasted_memory']), 'files_cached' => number_format($opcache_status['opcache_statistics']['num_cached_scripts']), 'hits_size' => number_format($opcache_status['opcache_statistics']['hits']), 'miss_size' => number_format($opcache_status['opcache_statistics']['misses']), 'blacklist_miss_size' => number_format($opcache_status['opcache_statistics']['blacklist_misses']), 'num_cached_keys_size' => number_format($opcache_status['opcache_statistics']['num_cached_keys']), 'max_cached_keys_size' => number_format($opcache_status['opcache_statistics']['max_cached_keys']), ) ); $threshold = ''; if ($data['used_memory_percentage'] >= $settings['used_memory_percentage_high_threshold']) { $threshold = ' high'; } elseif ($data['used_memory_percentage'] >= $settings['used_memory_percentage_mid_threshold']) { $threshold = ' mid'; } if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' ) { echo json_encode($data); exit; } $host = (function_exists('gethostname') ? gethostname() : (php_uname('n') ?: (empty($_SERVER['SERVER_NAME']) ? $_SERVER['HOST_NAME'] : $_SERVER['SERVER_NAME'] ) ) ); ?> <!doctype html> <html> <head> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script> <link href="//fonts.googleapis.com/css?family=Roboto" rel="stylesheet" type="text/css"> <style type="text/css"> html{font-family:sans-serif;font-size:100%;line-height:1.2;padding:2em;} body {font-size:75%;} .container{overflow:auto;width:100%;position:relative;} #info{margin-right:290px;} #counts{position:absolute;top:0;right:0;width:280px;} #counts div{ padding:1em; margin-bottom:1em; border-radius: 5px; background-p_w_picpath: linear-gradient(bottom, #B7C8CC 21%, #D5DEE0 60%, #E0ECEF 80%); background-p_w_picpath: -webkit-gradient(linear,left bottom,left top,color-stop(0.21, #B7C8CC),color-stop(0.6, #D5DEE0),color-stop(0.8, #E0ECEF)); } #counts p {text-align:center;} #counts div.values p {text-align:left;} #counts p span{font-family:'Roboto',sans-serif;} #counts p span.large{display:block;line-height:90%;font-size:800%;} table { margin: 0 0 1em 0; border-collapse: collapse; border-color: #fff; width: 100%; } table caption { text-align: left; font-size: 1.5em; } table tr { background-color: #99D0DF; border-color: #fff; } table th { text-align: left; padding: 6px; background-color: #0BA0C8; color: #fff; border-color: #fff; } table td { padding: 4px 6px; line-height: 1.4em; vertical-align: top; border-color: #fff; } table tr.odd { background-color: #EFFEFF; } table tr.even { background-color: #E0ECEF; } table tr.highlight { background-color: #61C4DF; } td.pathname p { margin-bottom: 0.25em; } .wsnw { white-space: nowrap; } .low{color:#000000;} .mid{color:#550000;} .high{color:#FF0000;} .invalid{color:#FF4545;} span.showmore span.button { display: inline-block; margin-right: 5px; position: relative; top: -1px; color: #333333; background: none repeat scroll 0 0 #DDDDDD; border-radius: 2px 2px 2px 2px; font-size: 12px; font-weight: bold; height: 12px; line-height: 6px; padding: 0 5px; vertical-align: middle; cursor: pointer; } a.button { text-decoration: none; font-size: 110%; color: #292929; padding: 10px 26px; background: -moz-linear-gradient(top, #ffffff 0%, #b4b7b8); background: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#b4b7b8)); -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; border: 1px solid #a1a1a1; text-shadow: 0px -1px 0px rgba(000,000,000,0), 0px 1px 0px rgba(255,255,255,0.4); margin: 0 1em; white-space: nowrap; } span.showmore span.button:hover { background-color: #CCCCCC; } @media screen and (max-width: 700px) { #info{margin-right:auto;} #counts{position:relative;display:block;margin-bottom:2em;width:100%;} } @media screen and (max-width: 550px) { a.button{display:block;margin-bottom:2px;} #frmFilter{width:99% !important;} } </style> </head> <body> <div > <p> <a href="?page=overview" class="button">Overview</a> <a href="?page=files" class="button">File usage</a> <a href="?page=reset" class="button" confirm('Are you sure you want to reset the cache?');">Reset cache</a> </p> </div> <?php if ($page == 'overview'): ?> <h3>Overview</h3> <div class="container"> <div id="counts"> <div> <p><span class="large <?php echo $threshold; ?>"><span class="realtime" data-value="used_memory_percentage"><?php echo $data['used_memory_percentage']; ?></span>%</span><br/>memory usage</p> </div> <div> <p><span class="large"><span class="realtime" data-value="hit_rate"><?php echo $data['hit_rate_percentage']; ?></span>%</span><br/>hit rate</p> </div> <div class="values"> <p><b>total memory:</b> <span data-value="total_memory_size"><?php echo $data['total_memory_size']; ?></span></p> <p><b>used memory:</b> <span class="realtime" data-value="used_memory_size"><?php echo $data['used_memory_size']; ?></span></p> <p><b>free memory:</b> <span class="realtime" data-value="free_memory_size"><?php echo $data['free_memory_size']; ?></span></p> <p><b>wasted memory:</b> <span class="realtime" data-value="wasted_memory_size"><?php echo $data['wasted_memory_size']; ?></span> (<span class="realtime" data-value="wasted_percentage"><?php echo $data['wasted_percentage']; ?></span>%)</p> <p><b>number of cached files:</b> <span class="realtime" data-value="files_cached"><?php echo $data['files_cached']; ?></span></p> <p><b>number of hits:</b> <span class="realtime" data-value="hits_size"><?php echo $data['hits_size']; ?></span></p> <p><b>number of misses:</b> <span class="realtime" data-value="miss_size"><?php echo $data['miss_size']; ?></span></p> <p><b>blacklist misses:</b> <span class="realtime" data-value="blacklist_miss_size"><?php echo $data['blacklist_miss_size']; ?></span></p> <p><b>number of cached keys:</b> <span class="realtime" data-value="num_cached_keys_size"><?php echo $data['num_cached_keys_size']; ?></span></p> <p><b>max cached keys:</b> <span class="realtime" data-value="max_cached_keys_size"><?php echo $data['max_cached_keys_size']; ?></span></p> </div> <br /> <p><a href="#" id="toggleRealtime">Enable real-time update of stats</a></p> </div> <div id="info"> <table> <tr><th colspan="2">General info</th></tr> <tr class="<?php rc(); ?>"> <td>Zend OPcache</td> <td><?php echo $opcache_config['version']['version']; ?></td> </tr> <tr class="<?php rc(); ?>"> <td>PHP</td> <td><?php echo phpversion(); ?></td> </tr> <tr class="<?php rc(); ?>"> <td>Host</td> <td><?php echo $host; ?></td> </tr> <?php if (!empty($_SERVER['SERVER_SOFTWARE'])): ?> <tr class="<?php rc(); ?>"> <td>Server Software</td> <td><?php echo $_SERVER['SERVER_SOFTWARE']; ?></td> </tr> <?php endif; ?> <tr class="<?php rc(); ?>"> <td>Start time</td> <td><?php echo date_format(date_create("@{$data['start_time']}"), 'Y-m-d H:i:s'); ?></td> </tr> <tr class="<?php rc(); ?>"> <td>Last reset</td> <td><?php echo ($data['last_restart_time'] == 0 ? '<em>never</em>' : date_format(date_create("@{$data['last_restart_time']}"), 'Y-m-d H:i:s')); ?></td> </tr> </table> <table> <tr><th colspan="2">Directives</th></tr> <?php ksort($opcache_config['directives']); ?> <?php rc(0); foreach ($opcache_config['directives'] as $d => $v): ?> <tr class="<?php rc(); ?>"> <td><span title="<?php echo $d; ?>"><?php echo str_replace(array('opcache.', '_'), array('', ' '), $d); ?></span></td> <td><?php echo (is_bool($v) ? ($v ? '<i>true</i>' : '<i>false</i>') : (empty($v) ? '<i>no value</i>' : $v)); ?></td> </tr> <?php endforeach; ?> </table> <table> <tr><th>Available functions</th></tr> <?php rc(0); foreach ($opcache_funcs as $f): ?> <tr class="<?php rc(); ?>"> <td><a href="http://php.net/<?php echo $f; ?>" title="View manual page" target="_blank"><?php echo $f; ?></td> </tr> <?php endforeach; ?> </table> <br /> </div> </div> <script type="text/javascript"> $(function(){ var realtime = false; function ping() { $.ajax({ url: "#", dataType: "json", cache: false, success: function(data){ $('.realtime').each(function(){ $(this).text(data[$(this).attr('data-value')]); }); } }); } $('#toggleRealtime').click(function(){ if (realtime === false) { realtime = setInterval(function(){ping()}, 5000); $(this).text('Disable real-time update of stats'); } else { clearInterval(realtime); realtime = false; $(this).text('Enable real-time update of stats'); } }); }); </script> <?php endif; ?> <?php if ($page == 'files'): ?> <h3>File usage</h3> <p><label>Start typing to filter on script path<br/><input type="text" name="filter" id="frmFilter" /><label></p> <div class="container"> <h4><?php echo $data['files_cached']; ?> file<?php echo ($data['files_cached'] == 1 ? '' : 's'); ?> cached <span id="filterShowing"></span></h4> <table> <tr> <th>Script</th> <th>Details</th> </tr> <?php rc(0); foreach ($opcache_status['scripts'] as $s): ?> <tr class="<?php rc(); ?>"> <td class="pathname"><p><?php $base = basename($s['full_path']); $parts = array_filter(explode(DIRECTORY_SEPARATOR, dirname($s['full_path']))); if (!empty($settings['compress_path_threshold'])) { echo '<span class="showmore"><span class="button">…</span><span class="text" >' . DIRECTORY_SEPARATOR; echo join(DIRECTORY_SEPARATOR, array_slice($parts, 0, $settings['compress_path_threshold'])) . DIRECTORY_SEPARATOR; echo '</span>'; echo join(DIRECTORY_SEPARATOR, array_slice($parts, $settings['compress_path_threshold'])); if (count($parts) > $settings['compress_path_threshold']) { echo DIRECTORY_SEPARATOR; } echo "{$base}</span>"; } else { echo htmlentities($s['full_path'], ENT_COMPAT, 'UTF-8'); } ?></p> <?php if ($settings['allow_invalidate'] && function_exists('opcache_invalidate')): ?> <a href="?page=invalidate&file=<?php echo urlencode($s['full_path']); ?>">Force file invalidation</a> <?php endif; ?> </td> <td> <p> hits: <?php echo $s['hits']; ?>, memory: <?php echo memsize($s['memory_consumption']); ?><br /> last used: <?php echo date_format(date_create($s['last_used']), 'Y-m-d H:i:s'); ?> <?php if ($s['timestamp'] === 0): ?> <br /><i class="invalid">has been invalidated</i> <?php endif; ?> </p> </td> </tr> <?php endforeach; ?> </table> </div> <script type="text/javascript"> $(function(){ $('span.showmore span.button').click(function(){ if ($(this).next().is(":visible")) { $(this).next().hide(); $(this).css('padding-top', '0').text('…'); } else { $(this).next().show(); $(this).css('padding-top', '2px').text(''); } }); $('.container table').bind('paint', function(event, params) { var trs = $('tr:visible', $(this)).not(':first'); trs.removeClass('odd even') .filter(':odd').addClass('odd') .end() .filter(':even').addClass('even'); $('#filterShowing').text(($('#frmFilter').val().length ? trs.length + ' showing due to filter' : '' )); }); $('#frmFilter').bind('keyup', function(event){ $('td.pathname p').each(function(index){ if ($(this).text().toLowerCase().indexOf($('#frmFilter').val().toLowerCase()) == -1) { $(this).closest('tr').hide(); } else { $(this).closest('tr').show(); } }); $('.container table').trigger('paint'); }); }); </script> <?php endif; ?> </body> </html>
ocp.php
<?php /* OCP - Opcache Control Panel (aka Zend Optimizer+ Control Panel for PHP) Author: _ck_ (with contributions by GK, stasilok) Version: 0.1.6 Free for any kind of use or modification, I am not responsible for anything, please share your improvements * revision history 0.1.6 2013-04-12 moved meta to footer so graphs can be higher and reduce clutter 0.1.5 2013-04-12 added graphs to visualize cache state, please report any browser/style bugs 0.1.4 2013-04-09 added "recheck" to update files when using large revalidate_freq (or validate_timestamps=Off) 0.1.3 2013-03-30 show host and php version, can bookmark with hashtag ie. #statistics - needs new layout asap 0.1.2 2013-03-25 show optimization levels, number formatting, support for start_time in 7.0.2 0.1.1 2013-03-18 today Zend completely renamed Optimizer+ to OPcache, adjusted OCP to keep working 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 determine when a file was put into the cache - cannot change settings on the fly - cannot protect opcache functions by restricting execution to only specific scripts/paths * todo: Extract variables for prefered ordering and better layout instead of just dumping into tables File list filter */ // ini_set('display_errors',1); error_reporting(-1); if ( count(get_included_files())>1 || php_sapi_name()=='cli' || empty($_SERVER['REMOTE_ADDR']) ) { die; } // weak block against indirect access $time=time(); define('CACHEPREFIX',function_exists('opcache_reset')?'opcache_':(function_exists('accelerator_reset')?'accelerator_':'')); if ( !empty($_GET['RESET']) ) { if ( function_exists(CACHEPREFIX.'reset') ) { call_user_func(CACHEPREFIX.'reset'); } header( 'Location: '.str_replace('?'.$_SERVER['QUERY_STRING'],'',$_SERVER['REQUEST_URI']) ); exit; } if ( !empty($_GET['RECHECK']) ) { if ( function_exists(CACHEPREFIX.'invalidate') ) { $recheck=trim($_GET['RECHECK']); $files=call_user_func(CACHEPREFIX.'get_status'); if (!empty($files['scripts'])) { foreach ($files['scripts'] as $file=>$value) { if ( $recheck==='1' || strpos($file,$recheck)===0 ) call_user_func(CACHEPREFIX.'invalidate',$file); } } header( 'Location: '.str_replace('?'.$_SERVER['QUERY_STRING'],'',$_SERVER['REQUEST_URI']) ); } else { echo 'Sorry, this feature requires Zend Opcache newer than April 8th 2013'; } exit; } ?><!DOCTYPE html> <html> <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, h2, h3 {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; } .middle {vertical-align:middle;} td, th { border: 1px solid #000; font-size: 75%; vertical-align: baseline;} h2 {font-size: 150%;} h3 {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;} .white, .white a {color:#fff;} img {float: right; border: 0px;} hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000;} .meta, .small {font-size: 75%; } .meta {margin: 2em 0;} .meta a, th a {padding: 10px; white-space:nowrap; } .buttons {margin:0 0 1em;} .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;} #files td.v a {font-weight:bold; color:#9999cc; margin:0 10px 0 5px; text-decoration:none; font-size:120%;} #files td.v a:hover {font-weight:bold; color:#ee0000;} .graph {display:inline-block; width:145px; margin:1em 0 1em 1px; border:0; vertical-align:top;} .graph table {width:100%; height:150px; border:0; padding:0; margin:5px 0 0 0; position:relative;} .graph td {vertical-align:middle; border:0; padding:0 0 0 5px;} .graph .bar {width:25px; text-align:right; padding:0 2px; color:#fff;} .graph .total {width:34px; text-align:center; padding:0 5px 0 0;} .graph .total div {border:1px dashed #888; border-right:0; height:99%; width:12px; position:absolute; bottom:0; left:17px; z-index:-1;} .graph .total span {background:#fff; font-weight:bold;} .graph .actual {text-align:right; font-weight:bold; padding:0 5px 0 0;} .graph .red {background:#ee0000;} .graph .green {background:#00cc00;} .graph .brown {background:#8B4513;} </style> <!--[if lt IE 9]><script type="text/javascript" defer="defer"> window. i,t=document.getElementsByTagName('table');for(i=0;i<t.length;i++){if(t[i].parentNode.className=='graph')t[i].style.height=150-(t[i].clientHeight-150)+'px';}} </script><![endif]--> </head> <body> <div class="center"> <h2><a href="?">Opcache Control Panel</a></h2> <div class="buttons"> <a href="?ALL=1">Details</a> <a href="?FILES=1&GROUP=2&SORT=3">Files</a> <a href="?RESET=1" confirm('RESET cache ?')">Reset</a> <?php if ( function_exists(CACHEPREFIX.'invalidate') ) { ?> <a href="?RECHECK=1" confirm('Recheck all files in the cache ?')">Recheck</a> <?php } ?> <a href="?" onclick="window.location.reload(true); return false">Refresh</a> </div> <?php if ( !function_exists(CACHEPREFIX.'get_status') ) { echo '<h3>Opcache not detected?</h3>'; die; } if ( !empty($_GET['FILES']) ) { echo '<h3>files cached</h3>'; files_display(); echo '</div></body></html>'; exit; } if ( !(isset($_REQUEST['GRAPHS']) && !$_REQUEST['GRAPHS']) && CACHEPREFIX=='opcache_') { graphs_display(); if ( !empty($_REQUEST['GRAPHS']) ) { 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\+|OPcache).+?(\<table[^>]*\>.+?\<\/table\>).+?(\<table[^>]*\>.+?\<\/table\>)/s', $phpinfo, $opcache) ) { } // todo if ( function_exists(CACHEPREFIX.'get_configuration') ) { echo '<h3>general</h3>'; $configuration=call_user_func(CACHEPREFIX.'get_configuration'); } $host=function_exists('gethostname')?@gethostname():@php_uname('n'); if (empty($host)) { $host=empty($_SERVER['SERVER_NAME'])?$_SERVER['HOST_NAME']:$_SERVER['SERVER_NAME']; } $version=array('Host'=>$host); $version['PHP Version']='PHP '.(defined('PHP_VERSION')?PHP_VERSION:'???').' '.(defined('PHP_SAPI')?PHP_SAPI:'').' '.(defined('PHP_OS')?' '.PHP_OS:''); $version['Opcache Version']=empty($configuration['version']['version'])?'???':$configuration['version'][CACHEPREFIX.'product_name'].' '.$configuration['version']['version']; print_table($version); if ( !empty($opcache[2]) ) { echo preg_replace('/\<tr\>\<td class\="e"\>[^>]+\<\/td\>\<td class\="v"\>[0-9\,\. ]+\<\/td\>\<\/tr\>/','',$opcache[2]); } if ( function_exists(CACHEPREFIX.'get_status') && $status=call_user_func(CACHEPREFIX.'get_status') ) { $uptime=array(); if ( !empty($status[CACHEPREFIX.'statistics']['start_time']) ) { $uptime['uptime']=time_since($time,$status[CACHEPREFIX.'statistics']['start_time'],1,''); } if ( !empty($status[CACHEPREFIX.'statistics']['last_restart_time']) ) { $uptime['last_restart']=time_since($time,$status[CACHEPREFIX.'statistics']['last_restart_time']); } if (!empty($uptime)) {print_table($uptime);} if ( !empty($status['cache_full']) ) { $status['memory_usage']['cache_full']=$status['cache_full']; } echo '<h3 id="memory">memory</h3>'; print_table($status['memory_usage']); unset($status[CACHEPREFIX.'statistics']['start_time'],$status[CACHEPREFIX.'statistics']['last_restart_time']); echo '<h3 id="statistics">statistics</h3>'; print_table($status[CACHEPREFIX.'statistics']); } if ( empty($_GET['ALL']) ) { meta_display(); exit; } if ( !empty($configuration['blacklist']) ) { echo '<h3 id="blacklist">blacklist</h3>'; print_table($configuration['blacklist']); } if ( !empty($opcache[3]) ) { echo '<h3 id="runtime">runtime</h3>'; echo $opcache[3]; } $name='zend opcache'; $functions=get_extension_funcs($name); if (!$functions) { $name='zend optimizer+'; $functions=get_extension_funcs($name); } if ($functions) { echo '<h3 id="functions">functions</h3>'; print_table($functions); } else { $name=''; } $level=trim(CACHEPREFIX,'_').'.optimization_level'; if (isset($configuration['directives'][$level])) { echo '<h3 id="optimization">optimization levels</h3>'; $levelset=strrev(base_convert($configuration['directives'][$level], 10, 2)); $levels=array( 1=>'<a href="http://wikipedia.org/wiki/Common_subexpression_elimination">Constants subexpressions elimination</a> (CSE) true, false, null, etc.<br />Optimize series of ADD_STRING / ADD_CHAR<br />Convert CAST(IS_BOOL,x) into BOOL(x)<br />Convert <a href="http://www.php.net/manual/internals2.opcodes.init-fcall-by-name.php">INIT_FCALL_BY_NAME</a> + <a href="http://www.php.net/manual/internals2.opcodes.do-fcall-by-name.php">DO_FCALL_BY_NAME</a> into <a href="http://www.php.net/manual/internals2.opcodes.do-fcall.php">DO_FCALL</a>', 2=>'Convert constant operands to expected types<br />Convert conditional <a href="http://php.net/manual/internals2.opcodes.jmp.php">JMP</a> with constant operands<br />Optimize static <a href="http://php.net/manual/internals2.opcodes.brk.php">BRK</a> and <a href="<a href="http://php.net/manual/internals2.opcodes.cont.php">CONT</a>', 3=>'Convert $a = $a + expr into $a += expr<br />Convert $a++ into ++$a<br />Optimize series of <a href="http://php.net/manual/internals2.opcodes.jmp.php">JMP</a>', 4=>'PRINT and ECHO optimization (<a href="https://github.com/zend-dev/ZendOptimizerPlus/issues/73">defunct</a>)', 5=>'Block Optimization - most expensive pass<br />Performs many different optimization patterns based on <a href="http://wikipedia.org/wiki/Control_flow_graph">control flow graph</a> (CFG)', 9=>'Optimize <a href="http://wikipedia.org/wiki/Register_allocation">register allocation</a> (allows re-usage of temporary variables)', 10=>'Remove NOPs' ); echo '<table width="600" border="0" cellpadding="3"><tbody><tr class="h"><th>Pass</th><th>Description</th></tr>'; foreach ($levels as $pass=>$description) { $disabled=substr($levelset,$pass-1,1)!=='1' || $pass==4 ? ' white':''; echo '<tr><td class="v center middle'.$disabled.'">'.$pass.'</td><td class="v'.$disabled.'">'.$description.'</td></tr>'; } echo '</table>'; } if ( isset($_GET['DUMP']) ) { if ($name) { echo '<h3 id="ini">ini</h3>'; print_table(ini_get_all($name,true)); } foreach ($configuration as $key=>$value) { echo '<h3>',$key,'</h3>'; print_table($configuration[$key]); } exit; } meta_display(); echo '</div></body></html>'; exit; function time_since($time,$original,$extended=0,$text='ago') { $time = $time - $original; $day = $extended? floor($time/86400) : round($time/86400,0); $amount=0; $unit=''; if ( $time < 86400) { if ( $time < 60) { $amount=$time; $unit='second'; } elseif ( $time < 3600) { $amount=floor($time/60); $unit='minute'; } else { $amount=floor($time/3600); $unit='hour'; } } elseif ( $day < 14) { $amount=$day; $unit='day'; } elseif ( $day < 56) { $amount=floor($day/7); $unit='week'; } elseif ( $day < 672) { $amount=floor($day/30); $unit='month'; } else { $amount=intval(2*($day/365))/2; $unit='year'; } if ( $amount!=1) {$unit.='s';} if ($extended && $time>60) { $text=' and '.time_since($time,$time<86400?($time<3600?$amount*60:$amount*3600):$day*86400,0,'').$text; } return $amount.' '.$unit.' '.$text; } function print_table($array,$headers=false) { if ( empty($array) || !is_array($array) ) {return;} echo '<table border="0" cellpadding="3" width="600">'; if (!empty($headers)) { if (!is_array($headers)) {$headers=array_keys(reset($array));} echo '<tr class="h">'; foreach ($headers as $value) { echo '<th>',$value,'</th>'; } echo '</tr>'; } 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=call_user_func(CACHEPREFIX.'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" id="files"> <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><a title="recheck" href="?RECHECK=',rawurlencode($data['full_path']),'">x</a>',$data['full_path'],'</td>', ($group?'<td class="vr">'.number_format($data['files']).'</td>':''), '<td class="vr">',number_format(round($data['memory_consumption']/1024)),'K</td>', '<td class="vr">',number_format($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>'; } function graphs_display() { $graphs=array(); $colors=array('green','brown','red'); $primes=array(223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987); $configuration=call_user_func(CACHEPREFIX.'get_configuration'); $status=call_user_func(CACHEPREFIX.'get_status'); $graphs['memory']['total']=$configuration['directives']['opcache.memory_consumption']; $graphs['memory']['free']=$status['memory_usage']['free_memory']; $graphs['memory']['used']=$status['memory_usage']['used_memory']; $graphs['memory']['wasted']=$status['memory_usage']['wasted_memory']; $graphs['keys']['total']=$status[CACHEPREFIX.'statistics']['max_cached_keys']; foreach ($primes as $prime) { if ($prime>=$graphs['keys']['total']) { $graphs['keys']['total']=$prime; break;} } $graphs['keys']['free']=$graphs['keys']['total']-$status[CACHEPREFIX.'statistics']['num_cached_keys']; $graphs['keys']['scripts']=$status[CACHEPREFIX.'statistics']['num_cached_scripts']; $graphs['keys']['wasted']=$status[CACHEPREFIX.'statistics']['num_cached_keys']-$status[CACHEPREFIX.'statistics']['num_cached_scripts']; $graphs['hits']['total']=0; $graphs['hits']['hits']=$status[CACHEPREFIX.'statistics']['hits']; $graphs['hits']['misses']=$status[CACHEPREFIX.'statistics']['misses']; $graphs['hits']['blacklist']=$status[CACHEPREFIX.'statistics']['blacklist_misses']; $graphs['hits']['total']=array_sum($graphs['hits']); $graphs['restarts']['total']=0; $graphs['restarts']['manual']=$status[CACHEPREFIX.'statistics']['manual_restarts']; $graphs['restarts']['keys']=$status[CACHEPREFIX.'statistics']['hash_restarts']; $graphs['restarts']['memory']=$status[CACHEPREFIX.'statistics']['oom_restarts']; $graphs['restarts']['total']=array_sum($graphs['restarts']); foreach ( $graphs as $caption=>$graph) { echo '<div class="graph"><div class="h">',$caption,'</div><table border="0" cellpadding="0" cellspacing="0">'; foreach ($graph as $label=>$value) { if ($label=='total') { $key=0; $total=$value; $totaldisplay='<td rowspan="3" class="total"><span>'.($total>999999?round($total/1024/1024).'M':($total>9999?round($total/1024).'K':$total)).'</span><div></div></td>'; continue;} $percent=$total?floor($value*100/$total):''; $percent=!$percent||$percent>99?'':$percent.'%'; echo '<tr>',$totaldisplay,'<td class="actual">', ($value>999999?round($value/1024/1024).'M':($value>9999?round($value/1024).'K':$value)),'</td><td class="bar ',$colors[$key],'" height="',$percent,'">',$percent,'</td><td>',$label,'</td></tr>'; $key++; $totaldisplay=''; } echo '</table></div>',"\n"; } } function meta_display() { ?> <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://wiki.php.net/rfc/optimizerplus">wiki.php.net</a> | <a href="http://pecl.php.net/package/ZendOpcache">pecl</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 }
opcache.php
<?php if (!extension_loaded('Zend OPcache')) { echo '<div >You do not have the Zend OPcache extension loaded, sample data is being shown instead.</div>'; require 'data-sample.php'; } class OpCacheDataModel { private $_configuration; private $_status; private $_d3Scripts = array(); public function __construct() { $this->_configuration = opcache_get_configuration(); $this->_status = opcache_get_status(); } public function getPageTitle() { return 'PHP ' . phpversion() . " with OpCache {$this->_configuration['version']['version']}"; } public function getStatusDataRows() { $rows = array(); foreach ($this->_status as $key => $value) { if ($key === 'scripts') { continue; } if (is_array($value)) { foreach ($value as $k => $v) { if ($v === false) { $value = 'false'; } if ($v === true) { $value = 'true'; } if ($k === 'used_memory' || $k === 'free_memory' || $k === 'wasted_memory') { $v = $this->_size_for_humans( $v ); } if ($k === 'current_wasted_percentage' || $k === 'opcache_hit_rate') { $v = number_format( $v, 2 ) . '%'; } if ($k === 'blacklist_miss_ratio') { $v = number_format($v, 2) . '%'; } if ($k === 'start_time' || $k === 'last_restart_time') { $v = ($v ? date(DATE_RFC822, $v) : 'never'); } $rows[] = "<tr><th>$k</th><td>$v</td></tr>\n"; } continue; } if ($value === false) { $value = 'false'; } if ($value === true) { $value = 'true'; } $rows[] = "<tr><th>$key</th><td>$value</td></tr>\n"; } return implode("\n", $rows); } public function getConfigDataRows() { $rows = array(); foreach ($this->_configuration['directives'] as $key => $value) { if ($value === false) { $value = 'false'; } if ($value === true) { $value = 'true'; } if ($key == 'opcache.memory_consumption') { $value = $this->_size_for_humans($value); } $rows[] = "<tr><th>$key</th><td>$value</td></tr>\n"; } return implode("\n", $rows); } public function getScriptStatusRows() { foreach ($this->_status['scripts'] as $key => $data) { $dirs[dirname($key)][basename($key)] = $data; $this->_arrayPset($this->_d3Scripts, $key, array( 'name' => basename($key), 'size' => $data['memory_consumption'], )); } asort($dirs); $basename = ''; while (true) { if (count($this->_d3Scripts) !=1) break; $basename .= DIRECTORY_SEPARATOR . key($this->_d3Scripts); $this->_d3Scripts = reset($this->_d3Scripts); } $this->_d3Scripts = $this->_processPartition($this->_d3Scripts, $basename); $id = 1; $rows = array(); foreach ($dirs as $dir => $files) { $count = count($files); $file_plural = $count > 1 ? 's' : null; $m = 0; foreach ($files as $file => $data) { $m += $data["memory_consumption"]; } $m = $this->_size_for_humans($m); if ($count > 1) { $rows[] = '<tr>'; $rows[] = "<th class=\"clickable\" id=\"head-{$id}\" colspan=\"3\" '#row-{$id}')\">{$dir} ({$count} file{$file_plural}, {$m})</th>"; $rows[] = '</tr>'; } foreach ($files as $file => $data) { $rows[] = "<tr id=\"row-{$id}\">"; $rows[] = "<td>{$data["hits"]}</td>"; $rows[] = "<td>" . $this->_size_for_humans($data["memory_consumption"]) . "</td>"; $rows[] = $count > 1 ? "<td>{$file}</td>" : "<td>{$dir}/{$file}</td>"; $rows[] = '</tr>'; } ++$id; } return implode("\n", $rows); } public function getScriptStatusCount() { return count($this->_status["scripts"]); } public function getGraphDataSetJson() { $dataset = array(); $dataset['memory'] = array( $this->_status['memory_usage']['used_memory'], $this->_status['memory_usage']['free_memory'], $this->_status['memory_usage']['wasted_memory'], ); $dataset['keys'] = array( $this->_status['opcache_statistics']['num_cached_keys'], $this->_status['opcache_statistics']['max_cached_keys'] - $this->_status['opcache_statistics']['num_cached_keys'], 0 ); $dataset['hits'] = array( $this->_status['opcache_statistics']['misses'], $this->_status['opcache_statistics']['hits'], 0, ); $dataset['restarts'] = array( $this->_status['opcache_statistics']['oom_restarts'], $this->_status['opcache_statistics']['manual_restarts'], $this->_status['opcache_statistics']['hash_restarts'], ); return json_encode($dataset); } public function getHumanUsedMemory() { return $this->_size_for_humans($this->getUsedMemory()); } public function getHumanFreeMemory() { return $this->_size_for_humans($this->getFreeMemory()); } public function getHumanWastedMemory() { return $this->_size_for_humans($this->getWastedMemory()); } public function getUsedMemory() { return $this->_status['memory_usage']['used_memory']; } public function getFreeMemory() { return $this->_status['memory_usage']['free_memory']; } public function getWastedMemory() { return $this->_status['memory_usage']['wasted_memory']; } public function getWastedMemoryPercentage() { return number_format($this->_status['memory_usage']['current_wasted_percentage'], 2); } public function getD3Scripts() { return $this->_d3Scripts; } private function _processPartition($value, $name = null) { if (array_key_exists('size', $value)) { return $value; } $array = array('name' => $name,'children' => array()); foreach ($value as $k => $v) { $array['children'][] = $this->_processPartition($v, $k); } return $array; } private function _size_for_humans($bytes) { if ($bytes > 1048576) { return sprintf('%.2f MB', $bytes / 1048576); } else { if ($bytes > 1024) { return sprintf('%.2f kB', $bytes / 1024); } else { return sprintf('%d bytes', $bytes); } } } // Borrowed from Laravel private function _arrayPset(&$array, $key, $value) { if (is_null($key)) return $array = $value; $keys = explode(DIRECTORY_SEPARATOR, ltrim($key, DIRECTORY_SEPARATOR)); while (count($keys) > 1) { $key = array_shift($keys); if ( ! isset($array[$key]) || ! is_array($array[$key])) { $array[$key] = array(); } $array =& $array[$key]; } $array[array_shift($keys)] = $value; return $array; } } $dataModel = new OpCacheDataModel(); ?> <!DOCTYPE html> <meta charset="utf-8"> <html> <head> <style> body { font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; margin: 0; padding: 0; } #container { width: 1024px; margin: auto; position: relative; } h2 { padding: 10px 0; } table { border-collapse: collapse; } tbody tr:nth-child(even) { background-color: #eee; } p.capitalize { text-transform: capitalize; } .tabs { position: relative; float: left; width: 60%; } .tab { float: left; } .tab label { background: #eee; padding: 10px 12px; border: 1px solid #ccc; margin-left: -1px; position: relative; left: 1px; } .tab [type=radio] { display: none; } .tab th, .tab td { padding: 8px 12px; } .content { position: absolute; top: 28px; left: 0; background: white; border: 1px solid #ccc; height: 450px; width: 100%; overflow: auto; } .content table { width: 100%; } .content th, .tab:nth-child(3) td { text-align: left; } .content td { text-align: right; } .clickable { cursor: pointer; } [type=radio]:checked ~ label { background: white; border-bottom: 1px solid white; z-index: 2; } [type=radio]:checked ~ label ~ .content { z-index: 1; } #graph { float: right; width: 40%; position: relative; } #graph > form { position: absolute; right: 60px; top: -20px; } #graph > svg { position: absolute; top: 0; right: 0; } #stats { position: absolute; right: 125px; top: 145px; } #stats th, #stats td { padding: 6px 10px; font-size: 0.8em; } #partition { position: absolute; width: 100%; height: 100%; z-index: 10; top: 0; left: 0; background: #ddd; display: none; } #close-partition { display: none; position: absolute; z-index: 20; right: 15px; top: 15px; background: #f9373d; color: #fff; padding: 12px 15px; } #close-partition:hover { background: #D32F33; cursor: pointer; } #partition rect { stroke: #fff; fill: #aaa; fill-opacity: 1; } #partition rect.parent { cursor: pointer; fill: steelblue; } #partition text { pointer-events: none; } label { cursor: pointer; } </style> <script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.0.1/d3.v3.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script> var hidden = {}; function toggleVisible(head, row) { if (!hidden[row]) { d3.selectAll(row).transition().style('display', 'none'); hidden[row] = true; d3.select(head).transition().style('color', '#ccc'); } else { d3.selectAll(row).transition().style('display'); hidden[row] = false; d3.select(head).transition().style('color', '#000'); } } </script> <title><?php echo $dataModel->getPageTitle(); ?></title> </head> <body> <div id="container"> <h2><?php echo $dataModel->getPageTitle(); ?></h2> <div class="tabs"> <div class="tab"> <input type="radio" id="tab-status" name="tab-group-1" checked> <label for="tab-status">Status</label> <div class="content"> <table> <?php echo $dataModel->getStatusDataRows(); ?> </table> </div> </div> <div class="tab"> <input type="radio" id="tab-config" name="tab-group-1"> <label for="tab-config">Configuration</label> <div class="content"> <table> <?php echo $dataModel->getConfigDataRows(); ?> </table> </div> </div> <div class="tab"> <input type="radio" id="tab-scripts" name="tab-group-1"> <label for="tab-scripts">Scripts (<?php echo $dataModel->getScriptStatusCount(); ?>)</label> <div class="content"> <table > <tr> <th width="10%">Hits</th> <th width="20%">Memory</th> <th width="70%">Path</th> </tr> <?php echo $dataModel->getScriptStatusRows(); ?> </table> </div> </div> <div class="tab"> <input type="radio" id="tab-visualise" name="tab-group-1"> <label for="tab-visualise">Visualise Partition</label> <div class="content"></div> </div> </div> <div id="graph"> <form> <label><input type="radio" name="dataset" value="memory" checked> Memory</label> <label><input type="radio" name="dataset" value="keys"> Keys</label> <label><input type="radio" name="dataset" value="hits"> Hits</label> <label><input type="radio" name="dataset" value="restarts"> Restarts</label> </form> <div id="stats"></div> </div> </div> <div id="close-partition">✖ Close Visualisation</div> <div id="partition"></div> <script> var dataset = <?php echo $dataModel->getGraphDataSetJson(); ?> var width = 400, height = 400, radius = Math.min(width, height) / 2, colours = ['#B41F1F', '#1FB437', '#ff7f0e']; d3.scale.customColours = function() { return d3.scale.ordinal().range(colours); }; var colour = d3.scale.customColours(); var pie = d3.layout.pie().sort(null); var arc = d3.svg.arc().innerRadius(radius - 20).outerRadius(radius - 50); var svg = d3.select("#graph").append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); var path = svg.selectAll("path") .data(pie(dataset.memory)) .enter().append("path") .attr("fill", function(d, i) { return colour(i); }) .attr("d", arc) .each(function(d) { this._current = d; }); // store the initial values d3.selectAll("input").on("change", change); set_text("memory"); function set_text(t) { if (t === "memory") { d3.select("#stats").html( "<table><tr><th style='background:#B41F1F;'>Used</th><td><?php echo $dataModel->getHumanUsedMemory()?></td></tr>"+ "<tr><th style='background:#1FB437;'>Free</th><td><?php echo $dataModel->getHumanFreeMemory()?></td></tr>"+ "<tr><th style='background:#ff7f0e;' rowspan=\"2\">Wasted</th><td><?php echo $dataModel->getHumanWastedMemory()?></td></tr>"+ "<tr><td><?php echo $dataModel->getWastedMemoryPercentage()?>%</td></tr></table>" ); } else if (t === "keys") { d3.select("#stats").html( "<table><tr><th style='background:#B41F1F;'>Cached keys</th><td>"+dataset[t][0]+"</td></tr>"+ "<tr><th style='background:#1FB437;'>Free Keys</th><td>"+dataset[t][1]+"</td></tr></table>" ); } else if (t === "hits") { d3.select("#stats").html( "<table><tr><th style='background:#B41F1F;'>Misses</th><td>"+dataset[t][0]+"</td></tr>"+ "<tr><th style='background:#1FB437;'>Cache Hits</th><td>"+dataset[t][1]+"</td></tr></table>" ); } else if (t === "restarts") { d3.select("#stats").html( "<table><tr><th style='background:#B41F1F;'>Memory</th><td>"+dataset[t][0]+"</td></tr>"+ "<tr><th style='background:#1FB437;'>Manual</th><td>"+dataset[t][1]+"</td></tr>"+ "<tr><th style='background:#ff7f0e;'>Keys</th><td>"+dataset[t][2]+"</td></tr></table>" ); } } function change() { if (typeof dataset[this.value] !== 'undefined') { path = path.data(pie(dataset[this.value])); // update the data path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs set_text(this.value); } } function arcTween(a) { var i = d3.interpolate(this._current, a); this._current = i(0); return function(t) { return arc(i(t)); }; } function size_for_humans(bytes) { if (bytes > 1048576) { return (bytes/1048576).toFixed(2) + ' MB'; } else if (bytes > 1024) { return (bytes/1024).toFixed(2) + ' KB'; } else return bytes + ' bytes'; } var w = window.innerWidth, h = window.innerHeight, x = d3.scale.linear().range([0, w]), y = d3.scale.linear().range([0, h]); var vis = d3.select("#partition") .style("width", w + "px") .style("height", h + "px") .append("svg:svg") .attr("width", w) .attr("height", h); var partition = d3.layout.partition() .value(function(d) { return d.size; }); root = JSON.parse('<?php echo json_encode($dataModel->getD3Scripts()); ?>'); var g = vis.selectAll("g") .data(partition.nodes(root)) .enter().append("svg:g") .attr("transform", function(d) { return "translate(" + x(d.y) + "," + y(d.x) + ")"; }) .on("click", click); var kx = w / root.dx, ky = h / 1; g.append("svg:rect") .attr("width", root.dy * kx) .attr("height", function(d) { return d.dx * ky; }) .attr("class", function(d) { return d.children ? "parent" : "child"; }); g.append("svg:text") .attr("transform", transform) .attr("dy", ".35em") .style("opacity", function(d) { return d.dx * ky > 12 ? 1 : 0; }) .text(function(d) { return d.name; }) d3.select(window) .on("click", function() { click(root); }) function click(d) { if (!d.children) return; kx = (d.y ? w - 40 : w) / (1 - d.y); ky = h / d.dx; x.domain([d.y, 1]).range([d.y ? 40 : 0, w]); y.domain([d.x, d.x + d.dx]); var t = g.transition() .duration(d3.event.altKey ? 7500 : 750) .attr("transform", function(d) { return "translate(" + x(d.y) + "," + y(d.x) + ")"; }); t.select("rect") .attr("width", d.dy * kx) .attr("height", function(d) { return d.dx * ky; }); t.select("text") .attr("transform", transform) .style("opacity", function(d) { return d.dx * ky > 12 ? 1 : 0; }); d3.event.stopPropagation(); } function transform(d) { return "translate(8," + d.dx * ky / 2 + ")"; } $(document).ready(function() { function handleVisualisationToggle(close) { $('#partition, #close-partition').fadeToggle(); // Is the visualisation being closed? If so show the status tab again if (close) { $('#tab-visualise').removeAttr('checked'); $('#tab-status').trigger('click'); } } $('label[for="tab-visualise"], #close-partition').on('click', function() { handleVisualisationToggle(($(this).attr('id') === 'close-partition')); }); $(document).keyup(function(e) { if (e.keyCode == 27) handleVisualisationToggle(true); }); }); </script> </body> </html>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。