opcache php54,WBB - Opcache – 加速PHP利器,查看opcache状态的方法

葛晔
2023-12-01

define('THOUSAND_SEPARATOR',true);

if (!extension_loaded('Zend OPcache')) {

echo '

You do not have the Zend OPcache extension loaded, sample data is being shown instead.
';

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[] = "

$k$v\n";

}

continue;

}

if ($value === false) {

$value = 'false';

}

if ($value === true) {

$value = 'true';

}

$rows[] = "

$key$value\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[] = "

$key$value\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[] = '

';

$rows[] = "

{$dir} ({$count} file{$file_plural}, {$m})";

$rows[] = '

';

}

foreach ($files as $file => $data) {

$rows[] = "

";

$rows[] = "

" . $this->_format_value($data["hits"]) . "";

$rows[] = "

" . $this->_size_for_humans($data["memory_consumption"]) . "";

$rows[] = $count > 1 ? "

{$file}" : "{$dir}/{$file}";

$rows[] = '

';

}

++$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();

?>

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;

}

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');

}

}

<?php echo $dataModel->getPageTitle(); ?>

<?php echo $dataModel->getPageTitle(); ?>

Status

<?php echo $dataModel->getStatusDataRows(); ?>

Configuration

<?php echo $dataModel->getConfigDataRows(); ?>

Scripts (<?php echo $dataModel->getScriptStatusCount(); ?>)

HitsMemoryPath

<?php echo $dataModel->getScriptStatusRows(); ?>

Visualise Partition

Memory

Keys

Hits

Restarts

✖ Close Visualisation

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(

"

Used<?php echo $dataModel->getHumanUsedMemory()?>

"

Free<?php echo $dataModel->getHumanFreeMemory()?>"+

"

Wasted<?php echo $dataModel->getHumanWastedMemory()?>"+

"

<?php echo $dataModel->getWastedMemoryPercentage()?>%"

);

} else if (t === "keys") {

d3.select("#stats").html(

"

Cached keys"+format_value(dataset[t][0])+"

"

Free Keys"+format_value(dataset[t][1])+""

);

} else if (t === "hits") {

d3.select("#stats").html(

"

Misses"+format_value(dataset[t][0])+"

"

Cache Hits"+format_value(dataset[t][1])+""

);

} else if (t === "restarts") {

d3.select("#stats").html(

"

Memory"+dataset[t][0]+"

"

Manual"+dataset[t][1]+""+

"

Keys"+dataset[t][2]+""

);

}

}

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);

});

});

 类似资料: