Source of file opcache.php
Size: 23,761 Bytes - Last Modified: 2021-12-23T10:38:54+00:00
/var/www/docs.ssmods.com/process/src/code/tests/opcache.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767 | <?php require_once('FindSSEnvironment.php'); define('ADMIN_USERNAME', SS_DEFAULT_ADMIN_USERNAME); // Admin Username define('ADMIN_PASSWORD', SS_DEFAULT_ADMIN_PASSWORD); // Admin Password - CHANGE THIS TO ENABLE!!! ///////////////// Password protect //////////////////////////////////////////////////////////////// if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) || $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||$_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) { Header("WWW-Authenticate: Basic realm=\"Memcache Login\""); Header("HTTP/1.0 401 Unauthorized"); echo <<<EOB <html><body> <h1>Rejected!</h1> <big>Wrong Username or Password!</big> </body></html> EOB; exit; } define('THOUSAND_SEPARATOR', true); if (!extension_loaded('Zend OPcache')) { echo '<div style="background-color: #F2DEDE; color: #B94A48; padding: 1em;">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'); } if (THOUSAND_SEPARATOR === true && is_int($v)) { $v = number_format($v); } $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\" onclick=\"toggleVisible('#head-{$id}', '#row-{$id}')\">{$dir} ({$count} file{$file_plural}, {$m})</th>"; $rows[] = '</tr>'; } foreach ($files as $file => $data) { $rows[] = "<tr id=\"row-{$id}\">"; $rows[] = "<td>" . $this->_format_value($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'], ); if (THOUSAND_SEPARATOR === true) { $dataset['TSEP'] = 1; } else { $dataset['TSEP'] = 0; } 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 _format_value($value) { if (THOUSAND_SEPARATOR === true) { return number_format($value); } else { return $value; } } 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; } h1 { 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"> <h1><?php echo $dataModel->getPageTitle(); ?></h1> <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 style="font-size:0.8em;"> <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>"+format_value(dataset[t][0])+"</td></tr>"+ "<tr><th style='background:#1FB437;'>Free Keys</th><td>"+format_value(dataset[t][1])+"</td></tr></table>" ); } else if (t === "hits") { d3.select("#stats").html( "<table><tr><th style='background:#B41F1F;'>Misses</th><td>"+format_value(dataset[t][0])+"</td></tr>"+ "<tr><th style='background:#1FB437;'>Cache Hits</th><td>"+format_value(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() { // Filter out any zero values to see if there is anything left var remove_zero_values = dataset[this.value].filter(function(value) { return value > 0; }); // Skip if the value is undefined for some reason if (typeof dataset[this.value] !== 'undefined' && remove_zero_values.length > 0) { $('#graph').find('> svg').show(); path = path.data(pie(dataset[this.value])); // update the data path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs // Hide the graph if we can't draw it correctly, not ideal but this works } else { $('#graph').find('> svg').hide(); } 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'; } function format_value(value) { if (dataset["TSEP"] == 1) { return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } else { return value; } } 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> |