integrate opcache-gui data from amnuts/opcache-gui as intended; refs #1151

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann 2023-06-12 12:15:52 +02:00
parent 257ef4c059
commit da7309c41e
No known key found for this signature in database
GPG Key ID: C121F97338D7A352
5 changed files with 85 additions and 240 deletions

View File

@ -33,9 +33,9 @@ const AREA = 'admin';
require __DIR__ . '/lib/init.php';
use Froxlor\FroxlorLogger;
use Froxlor\UI\HTML;
use Froxlor\UI\Panel\UI;
use Froxlor\UI\Response;
use Froxlor\UI\HTML;
if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_serversettings'] == '1') {
if ($_POST['send'] == 'send') {
@ -57,252 +57,30 @@ if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_
}
}
if (!function_exists('opcache_get_configuration')) {
if (!extension_loaded('Zend OPcache')) {
Response::standardError(lng('error.no_opcacheinfo'));
}
$ocEnabled = ini_get('opcache.enable');
if (empty($ocEnabled)) {
Response::standardError(lng('error.inactive_opcacheinfo'));
}
if ($page == 'showinfo' && $userinfo['change_serversettings'] == '1') {
$time = time();
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed OPcache info");
$optimizationLevels = [
1 << 0 => 'CSE, STRING construction',
1 << 1 => 'Constant conversion and jumps',
1 << 2 => '++, +=, series of jumps',
1 << 3 => 'INIT_FCALL_BY_NAME -> DO_FCALL',
1 << 4 => 'CFG based optimization',
1 << 5 => 'DFA based optimization',
1 << 6 => 'CALL GRAPH optimization',
1 << 7 => 'SCCP (constant propagation)',
1 << 8 => 'TMP VAR usage',
1 << 9 => 'NOP removal',
1 << 10 => 'Merge equal constants',
1 << 11 => 'Adjust used stack',
1 << 12 => 'Remove unused variables',
1 << 13 => 'DCE (dead code elimination)',
1 << 14 => '(unsafe) Collect constants',
1 << 15 => 'Inline functions'
];
$jitModes = [
[
'flag' => 'CPU-specific optimization',
'value' => [
'Disable CPU-specific optimization',
'Enable use of AVX, if the CPU supports it'
]
],
[
'flag' => 'Register allocation',
'value' => [
'Do not perform register allocation',
'Perform block-local register allocation',
'Perform global register allocation'
]
],
[
'flag' => 'Trigger',
'value' => [
'Compile all functions on script load',
'Compile functions on first execution',
'Profile functions on first request and compile the hottest functions afterwards',
'Profile on the fly and compile hot functions',
'Currently unused',
'Use tracing JIT. Profile on the fly and compile traces for hot code segments'
]
],
[
'flag' => 'Optimization level',
'value' => [
'No JIT',
'Minimal JIT (call standard VM handlers)',
'Inline VM handlers',
'Use type inference',
'Use call graph',
'Optimize whole script'
]
]
];
$jitModeMapping = [
'tracing' => 1254,
'on' => 1254,
'function' => 1205
];
$status = opcache_get_status(false);
$config = opcache_get_configuration();
$missingConfig = array_diff_key(ini_get_all('zend opcache', false), $config['directives']);
if (!empty($missingConfig)) {
$config['directives'] = array_merge($config['directives'], $missingConfig);
}
$files = [];
if (!empty($status['scripts'])) {
uasort($status['scripts'], static function ($a, $b) {
return $a['hits'] <=> $b['hits'];
});
foreach ($status['scripts'] as &$file) {
$file['full_path'] = str_replace('\\', '/', $file['full_path']);
$file['readable'] = [
'hits' => number_format($file['hits']),
'memory_consumption' => bsize($file['memory_consumption'])
];
}
$files = array_values($status['scripts']);
}
if ($config['directives']['opcache.file_cache_only'] || !empty($status['file_cache_only'])) {
$overview = false;
} else {
$status['opcache_statistics']['start_time'] = $status['opcache_statistics']['start_time'] ?? time();
$status['opcache_statistics']['last_restart_time'] = $status['opcache_statistics']['last_restart_time'] ?? time();
$overview = array_merge(
$status['memory_usage'],
$status['opcache_statistics'],
[
'total_memory' => $config['directives']['opcache.memory_consumption'],
'used_memory_percentage' => round(100 * (
($status['memory_usage']['used_memory'] + $status['memory_usage']['wasted_memory'])
/ $config['directives']['opcache.memory_consumption']
)),
'hit_rate_percentage' => round($status['opcache_statistics']['opcache_hit_rate']),
'used_key_percentage' => round(100 * ($status['opcache_statistics']['num_cached_keys']
/ $status['opcache_statistics']['max_cached_keys']
)),
'wasted_percentage' => round($status['memory_usage']['current_wasted_percentage'], 2),
'readable' => [
'total_memory' => bsize($config['directives']['opcache.memory_consumption']),
'used_memory' => bsize($status['memory_usage']['used_memory']),
'free_memory' => bsize($status['memory_usage']['free_memory']),
'wasted_memory' => bsize($status['memory_usage']['wasted_memory']),
'num_cached_scripts' => number_format($status['opcache_statistics']['num_cached_scripts']),
'hits' => number_format($status['opcache_statistics']['hits']),
'misses' => number_format($status['opcache_statistics']['misses']),
'blacklist_miss' => number_format($status['opcache_statistics']['blacklist_misses']),
'num_cached_keys' => number_format($status['opcache_statistics']['num_cached_keys']),
'max_cached_keys' => number_format($status['opcache_statistics']['max_cached_keys']),
'interned' => null,
'start_time' => (new DateTimeImmutable("@{$status['opcache_statistics']['start_time']}"))
->setTimezone(new DateTimeZone(date_default_timezone_get()))
->format('Y-m-d H:i:s'),
'last_restart_time' => ($status['opcache_statistics']['last_restart_time'] == 0
? 'never'
: (new DateTimeImmutable("@{$status['opcache_statistics']['last_restart_time']}"))
->setTimezone(new DateTimeZone(date_default_timezone_get()))
->format('Y-m-d H:i:s')
)
]
]
);
}
$preload = [];
if (!empty($status['preload_statistics']['scripts'])) {
$preload = $status['preload_statistics']['scripts'];
sort($preload, SORT_STRING);
if ($overview) {
$overview['preload_memory'] = $status['preload_statistics']['memory_consumption'];
$overview['readable']['preload_memory'] = bsize($status['preload_statistics']['memory_consumption']);
}
}
if (!empty($status['interned_strings_usage'])) {
$overview['readable']['interned'] = [
'buffer_size' => bsize($status['interned_strings_usage']['buffer_size']),
'strings_used_memory' => bsize($status['interned_strings_usage']['used_memory']),
'strings_free_memory' => bsize($status['interned_strings_usage']['free_memory']),
'number_of_strings' => number_format($status['interned_strings_usage']['number_of_strings'])
];
}
if ($overview && !empty($status['jit'])) {
$overview['jit_buffer_used_percentage'] = ($status['jit']['buffer_size']
? round(100 * (($status['jit']['buffer_size'] - $status['jit']['buffer_free']) / $status['jit']['buffer_size']))
: 0
);
$overview['readable'] = array_merge($overview['readable'], [
'jit_buffer_size' => bsize($status['jit']['buffer_size']),
'jit_buffer_free' => bsize($status['jit']['buffer_free'])
]);
}
$directives = [];
ksort($config['directives']);
foreach ($config['directives'] as $k => $v) {
if (in_array($k, ['opcache.max_file_size', 'opcache.memory_consumption', 'opcache.jit_buffer_size']) && $v) {
$v = bsize($v) . " ({$v})";
} elseif ($k === 'opcache.optimization_level') {
$levels = [];
foreach ($optimizationLevels as $level => $info) {
if ($level & $v) {
$levels[] = "{$info} [{$level}]";
}
}
$v = $levels ?: 'none';
} elseif ($k === 'opcache.jit') {
if ($v === '1') {
$v = 'on';
}
if (isset($jitModeMapping[$v]) || is_numeric($v)) {
$levels = [];
foreach (str_split((string)($jitModeMapping[$v] ?? $v)) as $type => $level) {
$levels[] = "{$level}: {$jitModes[$type]['value'][$level]} ({$jitModes[$type]['flag']})";
}
$v = [$v, $levels];
} elseif (empty($v) || strtolower($v) === 'off') {
$v = 'Off';
}
}
$directives[] = [
'k' => $k,
'v' => $v
];
}
$version = array_merge(
$config['version'],
[
'php' => phpversion(),
'server' => $_SERVER['SERVER_SOFTWARE'] ?: '',
'host' => (function_exists('gethostname')
? gethostname()
: (php_uname('n')
?: (empty($_SERVER['SERVER_NAME'])
? $_SERVER['HOST_NAME']
: $_SERVER['SERVER_NAME']
)
)
)
]
);
$opcache = (new \Amnuts\Opcache\Service())->getData();
UI::view('settings/opcacheinfo.html.twig', [
'opcacheinfo' => [
'version' => $version,
'overview' => $overview,
'files' => $files,
'preload' => $preload,
'directives' => $directives,
'blacklist' => $config['blacklist'],
'functions' => get_extension_funcs('Zend OPcache')
'version' => $opcache['version'],
'overview' => $opcache['overview'],
'files' => $opcache['files'],
'preload' => $opcache['preload'],
'directives' => $opcache['directives'],
'blacklist' => $opcache['blacklist'],
'functions' => $opcache['functions'],
]
]);
}
function bsize($size)
{
$i = 0;
$val = ['b', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
while (($size / 1024) > 1) {
$size /= 1024;
++$i;
}
return sprintf(
'%.2f%s%s',
$size,
'',
$val[$i]
);
}

View File

@ -54,7 +54,8 @@
"twig/twig": "^3.3",
"erusev/parsedown": "^1.7",
"symfony/console": "^5.4",
"pear/net_dns2": "^1.5"
"pear/net_dns2": "^1.5",
"amnuts/opcache-gui": "^3.4"
},
"require-dev": {
"phpunit/phpunit": "^9",

64
composer.lock generated
View File

@ -4,8 +4,70 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2de39e6b85579ce1f0c2f7a16d57ede3",
"content-hash": "9ce9c044d979a2358438b876c3c73561",
"packages": [
{
"name": "amnuts/opcache-gui",
"version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/amnuts/opcache-gui.git",
"reference": "a4af194185bcda734cf3e15e877b217153fffd2b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amnuts/opcache-gui/zipball/a4af194185bcda734cf3e15e877b217153fffd2b",
"reference": "a4af194185bcda734cf3e15e877b217153fffd2b",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-zend-opcache": "*",
"php": ">=7.1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Amnuts\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Andrew Collington",
"email": "andy@amnuts.com",
"homepage": "https://blog.amnuts.com/",
"role": "Developer"
},
{
"name": "Contributors",
"homepage": "https://github.com/amnuts/opcache-gui/graphs/contributors"
}
],
"description": "A clean, effective and responsive interface for Zend OPcache, with real(ish)-time monitoring, filtering and the ability to invalidate files",
"keywords": [
"Opcache",
"cache",
"gui",
"interface",
"opcodes"
],
"support": {
"email": "andy@amnuts.com",
"issues": "https://github.com/amnuts/opcache-gui/issues",
"source": "https://github.com/amnuts/opcache-gui/tree/3.4.0"
},
"funding": [
{
"url": "https://github.com/amnuts",
"type": "github"
}
],
"time": "2022-08-02T23:08:34+00:00"
},
{
"name": "erusev/parsedown",
"version": "1.7.4",

View File

@ -879,6 +879,9 @@ return [
'moveofcustomerfailed' => 'Das Verschieben des Kunden ist fehlgeschlagen. Alle übrigen Änderungen wurden durchgeführt und gespeichert.<br><br>Fehlermeldung: %s',
'domain_import_error' => 'Der folgende Fehler trat beim Importieren der Domains auf: %s',
'fcgidandphpfpmnogoodtogether' => 'FCGID und PHP-FPM können nicht gleichzeitig aktiviert werden.',
'no_apcuinfo' => 'Keine APCu Cache Informationen verfügbar. APCu scheint nicht installiert zu sein.',
'no_opcacheinfo' => 'Keine OPCache Informationen verfügbar. OPCache scheint nicht installiert zu sein.',
'inactive_opcacheinfo' => 'OPCache ist installiert, aber nicht aktiviert.',
'nowildcardwithletsencrypt' => 'Let\'s Encrypt kann mittels ACME Wildcard-Domains nur via DNS validieren, sorry. Bitte den ServerAlias auf WWW setzen oder deaktivieren',
'customized_version' => 'Es scheint als wäre die Froxlor Installation angepasst worden. Kein Support, sorry.',
'autoupdate_0' => 'Unbekannter Fehler',

View File

@ -950,7 +950,8 @@ return [
'domain_import_error' => 'Following error occurred while importing domains: %s',
'fcgidandphpfpmnogoodtogether' => 'FCGID and PHP-FPM cannot be activated at the same time',
'no_apcuinfo' => 'No cache info available. APCu does not appear to be running.',
'no_opcacheinfo' => 'No cache info available. OPCache does not appear to be running.',
'no_opcacheinfo' => 'No OPCache info available. OPCache does not appear to be loaded.',
'inactive_opcacheinfo' => 'OPCache seems to be installed but not activated.',
'nowildcardwithletsencrypt' => 'Let\'s Encrypt cannot handle wildcard-domains using ACME in froxlor (requires dns-challenge), sorry. Please set the ServerAlias to WWW or disable it completely',
'customized_version' => 'It looks like your Froxlor installation has been modified, no support sorry.',
'autoupdate_0' => 'Unknown error',