PHPアプリケーションのパフォーマンス最適化において、OPcacheの適切な設定は極めて重要です。opcache_get_configuration
関数は、現在のOPcache設定を取得・解析するための必須ツールです。この記事では、基本的な使い方から高度な設定分析まで、実践的な活用方法を詳しく解説します。
opcache_get_configuration関数とは?
opcache_get_configuration
は、現在有効なOPcacheの設定値をすべて取得するPHP関数です。この関数を使用することで、設定の確認、診断、最適化の判断材料を得ることができます。
基本的な構文
array opcache_get_configuration()
パラメータ: なし
戻り値: OPcacheの設定情報を含む連想配列
基本的な使い方
シンプルな設定確認
<?php
// OPcache設定を取得
$config = opcache_get_configuration();
if ($config === false) {
echo "OPcacheが利用できません。\n";
exit;
}
// 基本的な設定値を表示
echo "=== OPcache基本設定 ===\n";
echo "有効: " . ($config['directives']['opcache.enable'] ? 'はい' : 'いいえ') . "\n";
echo "CLI有効: " . ($config['directives']['opcache.enable_cli'] ? 'はい' : 'いいえ') . "\n";
echo "メモリ使用量: " . number_format($config['directives']['opcache.memory_consumption'] / 1024 / 1024, 0) . "MB\n";
echo "最大ファイル数: " . number_format($config['directives']['opcache.max_accelerated_files']) . "\n";
echo "バージョン: " . $config['version']['version'] . "\n";
?>
詳細な設定表示
<?php
class OpcacheConfigurationAnalyzer {
private $config;
public function __construct() {
$this->config = opcache_get_configuration();
if ($this->config === false) {
throw new RuntimeException('OPcacheが利用できません');
}
}
public function displayFullConfiguration() {
echo "=== OPcache完全設定情報 ===\n\n";
// バージョン情報
$this->displayVersionInfo();
// ディレクティブ(設定値)
$this->displayDirectives();
// ブラックリスト
$this->displayBlacklist();
}
private function displayVersionInfo() {
echo "【バージョン情報】\n";
foreach ($this->config['version'] as $key => $value) {
echo " {$key}: {$value}\n";
}
echo "\n";
}
private function displayDirectives() {
echo "【設定ディレクティブ】\n";
// カテゴリ別に整理して表示
$categories = [
'general' => ['opcache.enable', 'opcache.enable_cli', 'opcache.use_cwd', 'opcache.validate_timestamps'],
'memory' => ['opcache.memory_consumption', 'opcache.interned_strings_buffer', 'opcache.max_wasted_percentage'],
'files' => ['opcache.max_accelerated_files', 'opcache.max_file_size', 'opcache.file_update_protection'],
'validation' => ['opcache.revalidate_freq', 'opcache.revalidate_path', 'opcache.save_comments'],
'optimization' => ['opcache.optimization_level', 'opcache.enable_file_override', 'opcache.fast_shutdown'],
'logging' => ['opcache.log_verbosity_level', 'opcache.error_log']
];
foreach ($categories as $category => $directives) {
echo "\n 【{$category}】\n";
foreach ($directives as $directive) {
if (isset($this->config['directives'][$directive])) {
$value = $this->config['directives'][$directive];
$formattedValue = $this->formatDirectiveValue($directive, $value);
echo " {$directive}: {$formattedValue}\n";
}
}
}
// その他の設定
echo "\n 【その他】\n";
foreach ($this->config['directives'] as $key => $value) {
$found = false;
foreach ($categories as $categoryDirectives) {
if (in_array($key, $categoryDirectives)) {
$found = true;
break;
}
}
if (!$found) {
$formattedValue = $this->formatDirectiveValue($key, $value);
echo " {$key}: {$formattedValue}\n";
}
}
echo "\n";
}
private function formatDirectiveValue($directive, $value) {
// 特定の設定値を読みやすい形式に変換
switch ($directive) {
case 'opcache.memory_consumption':
case 'opcache.interned_strings_buffer':
return number_format($value / 1024 / 1024, 1) . 'MB (' . number_format($value) . ' bytes)';
case 'opcache.max_file_size':
if ($value == 0) {
return '無制限';
}
return number_format($value / 1024 / 1024, 1) . 'MB (' . number_format($value) . ' bytes)';
case 'opcache.max_accelerated_files':
return number_format($value) . ' files';
case 'opcache.revalidate_freq':
return $value . '秒';
case 'opcache.file_update_protection':
return $value . '秒';
case 'opcache.max_wasted_percentage':
return $value . '%';
case 'opcache.optimization_level':
return '0x' . dechex($value) . ' (' . $value . ')';
default:
if (is_bool($value)) {
return $value ? 'Yes' : 'No';
}
return (string)$value;
}
}
private function displayBlacklist() {
echo "【ブラックリスト】\n";
if (empty($this->config['blacklist'])) {
echo " ブラックリストは設定されていません\n";
} else {
foreach ($this->config['blacklist'] as $pattern) {
echo " - {$pattern}\n";
}
}
echo "\n";
}
public function analyzeConfiguration() {
echo "=== 設定分析結果 ===\n\n";
$issues = [];
$recommendations = [];
// 基本的な問題をチェック
$directives = $this->config['directives'];
// OPcacheが無効
if (!$directives['opcache.enable']) {
$issues[] = 'OPcacheが無効になっています';
$recommendations[] = 'opcache.enable=1 に設定してください';
}
// メモリ不足の可能性
$memoryMB = $directives['opcache.memory_consumption'] / 1024 / 1024;
if ($memoryMB < 128) {
$issues[] = 'メモリ使用量が少ない可能性があります (' . $memoryMB . 'MB)';
$recommendations[] = 'opcache.memory_consumption を 128MB以上に設定することを検討してください';
}
// ファイル数制限
$maxFiles = $directives['opcache.max_accelerated_files'];
if ($maxFiles < 10000) {
$issues[] = '最大ファイル数が少ない可能性があります (' . number_format($maxFiles) . ')';
$recommendations[] = 'opcache.max_accelerated_files を 10000以上に設定することを検討してください';
}
// タイムスタンプ検証(本番環境での考慮事項)
if ($directives['opcache.validate_timestamps']) {
$issues[] = '本番環境でタイムスタンプ検証が有効です';
$recommendations[] = '本番環境では opcache.validate_timestamps=0 を検討してください';
}
// 結果を表示
if (empty($issues)) {
echo "✅ 設定に問題は見つかりませんでした。\n";
} else {
echo "⚠️ 発見された問題:\n";
foreach ($issues as $issue) {
echo " - {$issue}\n";
}
echo "\n💡 推奨事項:\n";
foreach ($recommendations as $recommendation) {
echo " - {$recommendation}\n";
}
}
return [
'issues' => $issues,
'recommendations' => $recommendations
];
}
}
// 使用例
try {
$analyzer = new OpcacheConfigurationAnalyzer();
$analyzer->displayFullConfiguration();
$analyzer->analyzeConfiguration();
} catch (RuntimeException $e) {
echo "エラー: " . $e->getMessage() . "\n";
}
?>
実践的な活用例
1. 設定の環境別比較
<?php
class EnvironmentConfigComparator {
public static function compareConfigurations($environments) {
echo "=== 環境別OPcache設定比較 ===\n\n";
$allConfigs = [];
// 各環境の設定を収集(実際には各環境で実行した結果を使用)
foreach ($environments as $env => $configData) {
$allConfigs[$env] = $configData;
}
// 重要な設定項目を比較
$importantDirectives = [
'opcache.enable',
'opcache.enable_cli',
'opcache.memory_consumption',
'opcache.max_accelerated_files',
'opcache.validate_timestamps',
'opcache.revalidate_freq',
'opcache.save_comments',
'opcache.optimization_level'
];
echo sprintf("%-35s", "設定項目");
foreach (array_keys($environments) as $env) {
echo sprintf("%-20s", strtoupper($env));
}
echo "\n" . str_repeat("-", 35 + count($environments) * 20) . "\n";
foreach ($importantDirectives as $directive) {
echo sprintf("%-35s", $directive);
$values = [];
foreach ($environments as $env => $configData) {
$value = $configData['directives'][$directive] ?? 'N/A';
$values[] = $value;
echo sprintf("%-20s", self::formatValue($directive, $value));
}
// 値の一致チェック
if (count(array_unique($values)) > 1) {
echo " ⚠️ 不一致";
}
echo "\n";
}
echo "\n";
// 推奨事項を表示
self::displayEnvironmentRecommendations($allConfigs);
}
private static function formatValue($directive, $value) {
if ($value === 'N/A') return $value;
switch ($directive) {
case 'opcache.memory_consumption':
return number_format($value / 1024 / 1024, 0) . 'MB';
case 'opcache.max_accelerated_files':
return number_format($value);
case 'opcache.revalidate_freq':
return $value . 's';
default:
if (is_bool($value)) {
return $value ? 'Yes' : 'No';
}
return (string)$value;
}
}
private static function displayEnvironmentRecommendations($configs) {
echo "=== 環境別推奨事項 ===\n\n";
foreach ($configs as $env => $config) {
echo "【" . strtoupper($env) . "】\n";
$directives = $config['directives'];
$recommendations = [];
switch ($env) {
case 'development':
if (!$directives['opcache.validate_timestamps']) {
$recommendations[] = 'opcache.validate_timestamps=1 にして開発効率を向上';
}
if ($directives['opcache.revalidate_freq'] > 2) {
$recommendations[] = 'opcache.revalidate_freq=2 にして変更をすぐ反映';
}
if (!$directives['opcache.save_comments']) {
$recommendations[] = 'opcache.save_comments=1 にしてデバッグを容易に';
}
break;
case 'staging':
if ($directives['opcache.validate_timestamps']) {
$recommendations[] = 'opcache.validate_timestamps=0 にして本番環境に近づける';
}
if ($directives['opcache.revalidate_freq'] < 60) {
$recommendations[] = 'opcache.revalidate_freq=60 にしてパフォーマンス重視';
}
break;
case 'production':
if ($directives['opcache.validate_timestamps']) {
$recommendations[] = 'opcache.validate_timestamps=0 にして最高のパフォーマンスを実現';
}
if ($directives['opcache.save_comments']) {
$recommendations[] = 'opcache.save_comments=0 にしてメモリを節約';
}
if (($directives['opcache.memory_consumption'] / 1024 / 1024) < 256) {
$recommendations[] = 'opcache.memory_consumption を256MB以上に増加';
}
break;
}
if (empty($recommendations)) {
echo " ✅ 現在の設定は適切です\n";
} else {
foreach ($recommendations as $rec) {
echo " 💡 {$rec}\n";
}
}
echo "\n";
}
}
}
// 使用例(実際の設定データ例)
$environmentConfigs = [
'development' => [
'directives' => [
'opcache.enable' => true,
'opcache.enable_cli' => true,
'opcache.memory_consumption' => 134217728, // 128MB
'opcache.max_accelerated_files' => 4000,
'opcache.validate_timestamps' => true,
'opcache.revalidate_freq' => 2,
'opcache.save_comments' => true,
'opcache.optimization_level' => 0x7FFFBFFF
]
],
'production' => [
'directives' => [
'opcache.enable' => true,
'opcache.enable_cli' => false,
'opcache.memory_consumption' => 268435456, // 256MB
'opcache.max_accelerated_files' => 20000,
'opcache.validate_timestamps' => false,
'opcache.revalidate_freq' => 0,
'opcache.save_comments' => false,
'opcache.optimization_level' => 0x7FFFBFFF
]
]
];
EnvironmentConfigComparator::compareConfigurations($environmentConfigs);
?>
2. 設定の妥当性チェッカー
<?php
class OpcacheConfigurationValidator {
private $config;
private $issues = [];
private $warnings = [];
private $recommendations = [];
public function __construct() {
$this->config = opcache_get_configuration();
if ($this->config === false) {
throw new RuntimeException('OPcacheが利用できません');
}
}
public function validateConfiguration() {
echo "=== OPcache設定妥当性チェック ===\n\n";
$this->checkBasicSettings();
$this->checkMemorySettings();
$this->checkPerformanceSettings();
$this->checkSecuritySettings();
$this->checkCompatibilitySettings();
$this->displayResults();
return [
'issues' => $this->issues,
'warnings' => $this->warnings,
'recommendations' => $this->recommendations
];
}
private function checkBasicSettings() {
$directives = $this->config['directives'];
// OPcache有効性チェック
if (!$directives['opcache.enable']) {
$this->issues[] = 'OPcacheが無効です';
$this->recommendations[] = 'opcache.enable=1 に設定してください';
}
// CLI設定チェック
if (php_sapi_name() === 'cli' && !$directives['opcache.enable_cli']) {
$this->warnings[] = 'CLI環境でOPcacheが無効です';
$this->recommendations[] = 'CLIでもOPcacheを利用する場合は opcache.enable_cli=1 に設定';
}
}
private function checkMemorySettings() {
$directives = $this->config['directives'];
// メモリ使用量チェック
$memoryMB = $directives['opcache.memory_consumption'] / 1024 / 1024;
if ($memoryMB < 64) {
$this->issues[] = "メモリ使用量が非常に少ないです ({$memoryMB}MB)";
$this->recommendations[] = 'opcache.memory_consumption を最低128MB以上に設定';
} elseif ($memoryMB < 128) {
$this->warnings[] = "メモリ使用量が少ない可能性があります ({$memoryMB}MB)";
$this->recommendations[] = 'アプリケーションサイズに応じてメモリを増加を検討';
}
// 文字列バッファチェック
$stringBufferMB = $directives['opcache.interned_strings_buffer'] / 1024 / 1024;
if ($stringBufferMB < 8) {
$this->warnings[] = "文字列バッファが小さい可能性があります ({$stringBufferMB}MB)";
$this->recommendations[] = 'opcache.interned_strings_buffer を16MB以上に設定を検討';
}
// 無駄領域の割合チェック
$wastedPercent = $directives['opcache.max_wasted_percentage'];
if ($wastedPercent > 10) {
$this->warnings[] = "無駄領域の許容割合が高いです ({$wastedPercent}%)";
$this->recommendations[] = 'opcache.max_wasted_percentage を5%以下に設定を検討';
}
}
private function checkPerformanceSettings() {
$directives = $this->config['directives'];
// ファイル数制限チェック
$maxFiles = $directives['opcache.max_accelerated_files'];
// 適切な値の範囲を定義(2の累乗に近い値が推奨)
$recommendedValues = [4000, 7963, 16229, 32531, 65000];
$nearestRecommended = null;
$minDiff = PHP_INT_MAX;
foreach ($recommendedValues as $recommended) {
$diff = abs($maxFiles - $recommended);
if ($diff < $minDiff) {
$minDiff = $diff;
$nearestRecommended = $recommended;
}
}
if ($maxFiles < 4000) {
$this->warnings[] = "最大ファイル数が少ない可能性があります (" . number_format($maxFiles) . ")";
$this->recommendations[] = "opcache.max_accelerated_files を {$nearestRecommended} に設定を検討";
}
// 最適化レベルチェック
$optimizationLevel = $directives['opcache.optimization_level'];
if ($optimizationLevel !== 0x7FFFBFFF) {
$this->warnings[] = "最適化レベルがデフォルト値ではありません (0x" . dechex($optimizationLevel) . ")";
$this->recommendations[] = '特別な理由がない限り、デフォルト値 0x7FFFBFFF の使用を推奨';
}
// ファイルサイズ制限チェック
$maxFileSize = $directives['opcache.max_file_size'];
if ($maxFileSize > 0 && $maxFileSize < 1024 * 1024) { // 1MB未満
$this->warnings[] = "最大ファイルサイズ制限が厳しすぎる可能性があります";
$this->recommendations[] = 'opcache.max_file_size を2MB以上に設定を検討';
}
}
private function checkSecuritySettings() {
$directives = $this->config['directives'];
// ファイル更新保護チェック
$fileUpdateProtection = $directives['opcache.file_update_protection'];
if ($fileUpdateProtection < 2) {
$this->warnings[] = "ファイル更新保護時間が短いです ({$fileUpdateProtection}秒)";
$this->recommendations[] = 'opcache.file_update_protection を2秒以上に設定を推奨';
}
// タイムスタンプ検証の環境適合性チェック
$validateTimestamps = $directives['opcache.validate_timestamps'];
$isProduction = $this->detectProductionEnvironment();
if ($isProduction && $validateTimestamps) {
$this->warnings[] = '本番環境でタイムスタンプ検証が有効です';
$this->recommendations[] = '本番環境では opcache.validate_timestamps=0 にしてパフォーマンス向上';
} elseif (!$isProduction && !$validateTimestamps) {
$this->warnings[] = '開発環境でタイムスタンプ検証が無効です';
$this->recommendations[] = '開発環境では opcache.validate_timestamps=1 にして開発効率向上';
}
}
private function checkCompatibilitySettings() {
$directives = $this->config['directives'];
// コメント保存設定
$saveComments = $directives['opcache.save_comments'];
if (!$saveComments) {
$this->warnings[] = 'コメントが保存されていません';
$this->recommendations[] = 'DocBlockや型情報が必要な場合は opcache.save_comments=1 に設定';
}
// fast_shutdown設定(PHP 7.2以降では非推奨)
if (isset($directives['opcache.fast_shutdown']) && $directives['opcache.fast_shutdown'] && version_compare(PHP_VERSION, '7.2.0', '>=')) {
$this->warnings[] = 'opcache.fast_shutdown は PHP 7.2以降では非推奨です';
$this->recommendations[] = 'opcache.fast_shutdown=0 に設定することを推奨';
}
}
private function detectProductionEnvironment() {
// 環境検出のロジック(例)
$indicators = [
$_SERVER['SERVER_NAME'] ?? '',
$_SERVER['HTTP_HOST'] ?? '',
php_uname('n'),
getcwd()
];
$productionPatterns = [
'/prod/i',
'/production/i',
'/www\./',
'/live/i'
];
foreach ($indicators as $indicator) {
foreach ($productionPatterns as $pattern) {
if (preg_match($pattern, $indicator)) {
return true;
}
}
}
return false;
}
private function displayResults() {
echo "=== チェック結果 ===\n\n";
// 重要な問題
if (!empty($this->issues)) {
echo "🚨 重要な問題:\n";
foreach ($this->issues as $issue) {
echo " - {$issue}\n";
}
echo "\n";
}
// 警告
if (!empty($this->warnings)) {
echo "⚠️ 警告:\n";
foreach ($this->warnings as $warning) {
echo " - {$warning}\n";
}
echo "\n";
}
// 推奨事項
if (!empty($this->recommendations)) {
echo "💡 推奨事項:\n";
foreach ($this->recommendations as $recommendation) {
echo " - {$recommendation}\n";
}
echo "\n";
}
// 総合評価
if (empty($this->issues) && empty($this->warnings)) {
echo "✅ 設定は適切です!\n";
} elseif (empty($this->issues)) {
echo "✅ 基本的な設定は適切ですが、最適化の余地があります。\n";
} else {
echo "❌ 設定に問題があります。修正することを強く推奨します。\n";
}
echo "\n";
}
public function generateINIRecommendations() {
echo "=== 推奨php.ini設定 ===\n\n";
$currentEnv = $this->detectProductionEnvironment() ? 'production' : 'development';
echo "環境: " . strtoupper($currentEnv) . "\n\n";
if ($currentEnv === 'production') {
echo "; 本番環境推奨設定\n";
echo "opcache.enable=1\n";
echo "opcache.enable_cli=0\n";
echo "opcache.memory_consumption=256\n";
echo "opcache.interned_strings_buffer=16\n";
echo "opcache.max_accelerated_files=20000\n";
echo "opcache.validate_timestamps=0\n";
echo "opcache.revalidate_freq=0\n";
echo "opcache.save_comments=0\n";
echo "opcache.enable_file_override=1\n";
echo "opcache.max_wasted_percentage=5\n";
} else {
echo "; 開発環境推奨設定\n";
echo "opcache.enable=1\n";
echo "opcache.enable_cli=1\n";
echo "opcache.memory_consumption=128\n";
echo "opcache.interned_strings_buffer=8\n";
echo "opcache.max_accelerated_files=10000\n";
echo "opcache.validate_timestamps=1\n";
echo "opcache.revalidate_freq=2\n";
echo "opcache.save_comments=1\n";
echo "opcache.enable_file_override=0\n";
echo "opcache.max_wasted_percentage=10\n";
}
echo "\n";
}
}
// 使用例
try {
$validator = new OpcacheConfigurationValidator();
$validator->validateConfiguration();
$validator->generateINIRecommendations();
} catch (RuntimeException $e) {
echo "エラー: " . $e->getMessage() . "\n";
}
?>
3. リアルタイム設定監視
<?php
class OpcacheConfigurationMonitor {
private $configSnapshot;
private $logFile;
public function __construct($logFile = '/var/log/opcache-config-monitor.log') {
$this->logFile = $logFile;
$this->configSnapshot = null;
}
public function takeSnapshot() {
$config = opcache_get_configuration();
if ($config === false) {
throw new RuntimeException('OPcacheが利用できません');
}
$this->configSnapshot = [
'timestamp' => time(),
'config' => $config,
'checksum' => $this->calculateConfigChecksum($config)
];
$this->log('設定スナップショットを取得: チェックサム=' . $this->configSnapshot['checksum']);
return $this->configSnapshot;
}
public function compareWithSnapshot() {
if ($this->configSnapshot === null) {
throw new RuntimeException('比較用のスナップショットが存在しません');
}
$currentConfig = opcache_get_configuration();
if ($currentConfig === false) {
throw new RuntimeException('現在のOPcache設定を取得できません');
}
$currentChecksum = $this->calculateConfigChecksum($currentConfig);
$previousChecksum = $this->configSnapshot['checksum'];
if ($currentChecksum === $previousChecksum) {
$this->log('設定変更なし: チェックサム=' . $currentChecksum);
return ['changed' => false, 'changes' => []];
}
// 変更を詳細分析
$changes = $this->analyzeChanges($this->configSnapshot['config'], $currentConfig);
$this->log('設定変更を検出: ' . count($changes) . ' 項目変更');
foreach ($changes as $change) {
$this->log(" {$change['directive']}: {$change['old_value']} → {$change['new_value']}");
}
return [
'changed' => true,
'changes' => $changes,
'old_checksum' => $previousChecksum,
'new_checksum' => $currentChecksum
];
}
private function calculateConfigChecksum($config) {
// 設定のチェックサムを計算(バージョン情報は除外)
$relevantData = [
'directives' => $config['directives'],
'blacklist' => $config['blacklist']
];
return md5(serialize($relevantData));
}
private function analyzeChanges($oldConfig, $newConfig) {
$changes = [];
// ディレクティブの変更をチェック
foreach ($oldConfig['directives'] as $directive => $oldValue) {
$newValue = $newConfig['directives'][$directive] ?? null;
if ($newValue !== $oldValue) {
$changes[] = [
'type' => 'directive',
'directive' => $directive,
'old_value' => $this->formatValue($oldValue),
'new_value' => $this->formatValue($newValue),
'impact' => $this->assessChangeImpact($directive, $oldValue, $newValue)
];
}
}
// 新しいディレクティブをチェック
foreach ($newConfig['directives'] as $directive => $newValue) {
if (!isset($oldConfig['directives'][$directive])) {
$changes[] = [
'type' => 'directive_added',
'directive' => $directive,
'old_value' => 'N/A',
'new_value' => $this->formatValue($newValue),
'impact' => 'unknown'
];
}
}
// ブラックリストの変更をチェック
if ($oldConfig['blacklist'] !== $newConfig['blacklist']) {
$changes[] = [
'type' => 'blacklist',
'directive' => 'opcache.blacklist',
'old_value' => count($oldConfig['blacklist']) . ' entries',
'new_value' => count($newConfig['blacklist']) . ' entries',
'impact' => 'medium'
];
}
return $changes;
}
private function formatValue($value) {
if ($value === null) return 'null';
if (is_bool($value)) return $value ? 'true' : 'false';
if (is_numeric($value) && $value > 1000000) {
return number_format($value / 1024 / 1024, 1) . 'MB';
}
return (string)$value;
}
private function assessChangeImpact($directive, $oldValue, $newValue) {
// 変更の影響度を評価
$highImpactDirectives = [
'opcache.enable',
'opcache.memory_consumption',
'opcache.max_accelerated_files',
'opcache.validate_timestamps'
];
$mediumImpactDirectives = [
'opcache.revalidate_freq',
'opcache.save_comments',
'opcache.optimization_level',
'opcache.enable_cli'
];
if (in_array($directive, $highImpactDirectives)) {
return 'high';
} elseif (in_array($directive, $mediumImpactDirectives)) {
return 'medium';
} else {
return 'low';
}
}
private function log($message) {
$timestamp = date('Y-m-d H:i:s');
$logMessage = "[{$timestamp}] {$message}\n";
// ログファイルに書き込み
if (is_writable(dirname($this->logFile))) {
file_put_contents($this->logFile, $logMessage, FILE_APPEND | LOCK_EX);
}
// 標準出力にも表示
if (php_sapi_name() === 'cli') {
echo $logMessage;
}
}
public function startMonitoring($intervalSeconds = 300) {
echo "OPcache設定監視を開始します({$intervalSeconds}秒間隔)...\n";
// 初回スナップショット
$this->takeSnapshot();
while (true) {
sleep($intervalSeconds);
try {
$comparison = $this->compareWithSnapshot();
if ($comparison['changed']) {
echo "\n=== 設定変更検出 ===\n";
foreach ($comparison['changes'] as $change) {
$impact = strtoupper($change['impact']);
$icon = $impact === 'HIGH' ? '🚨' : ($impact === 'MEDIUM' ? '⚠️' : 'ℹ️');
echo "{$icon} [{$impact}] {$change['directive']}\n";
echo " 変更前: {$change['old_value']}\n";
echo " 変更後: {$change['new_value']}\n\n";
}
// スナップショットを更新
$this->takeSnapshot();
}
} catch (Exception $e) {
$this->log('監視エラー: ' . $e->getMessage());
echo "エラー: " . $e->getMessage() . "\n";
}
}
}
public function generateConfigReport() {
$config = opcache_get_configuration();
if ($config === false) {
return "OPcacheが利用できません。";
}
$report = "=== OPcache設定レポート ===\n";
$report .= "生成日時: " . date('Y-m-d H:i:s') . "\n";
$report .= "PHP バージョン: " . PHP_VERSION . "\n";
$report .= "OPcache バージョン: " . $config['version']['version'] . "\n\n";
// 重要な設定のサマリー
$directives = $config['directives'];
$report .= "【主要設定】\n";
$report .= sprintf(" 有効状態: %s\n", $directives['opcache.enable'] ? 'ON' : 'OFF');
$report .= sprintf(" メモリ使用量: %.0fMB\n", $directives['opcache.memory_consumption'] / 1024 / 1024);
$report .= sprintf(" 最大ファイル数: %s\n", number_format($directives['opcache.max_accelerated_files']));
$report .= sprintf(" タイムスタンプ検証: %s\n", $directives['opcache.validate_timestamps'] ? 'ON' : 'OFF');
$report .= sprintf(" 再検証頻度: %d秒\n", $directives['opcache.revalidate_freq']);
// パフォーマンス関連設定
$report .= "\n【パフォーマンス設定】\n";
$report .= sprintf(" 文字列バッファ: %.0fMB\n", $directives['opcache.interned_strings_buffer'] / 1024 / 1024);
$report .= sprintf(" 最大ファイルサイズ: %s\n",
$directives['opcache.max_file_size'] > 0 ?
number_format($directives['opcache.max_file_size'] / 1024 / 1024, 1) . 'MB' : '無制限');
$report .= sprintf(" 最適化レベル: 0x%X\n", $directives['opcache.optimization_level']);
$report .= sprintf(" コメント保存: %s\n", $directives['opcache.save_comments'] ? 'ON' : 'OFF');
// セキュリティ設定
$report .= "\n【セキュリティ設定】\n";
$report .= sprintf(" ファイル更新保護: %d秒\n", $directives['opcache.file_update_protection']);
$report .= sprintf(" パス再検証: %s\n", $directives['opcache.revalidate_path'] ? 'ON' : 'OFF');
// ブラックリスト
$report .= "\n【ブラックリスト】\n";
if (empty($config['blacklist'])) {
$report .= " 設定されていません\n";
} else {
foreach ($config['blacklist'] as $pattern) {
$report .= " - {$pattern}\n";
}
}
return $report;
}
}
// CLIでの使用例
if (php_sapi_name() === 'cli') {
$monitor = new OpcacheConfigurationMonitor();
$command = $argv[1] ?? 'help';
switch ($command) {
case 'snapshot':
$monitor->takeSnapshot();
echo "スナップショットを取得しました。\n";
break;
case 'compare':
try {
$result = $monitor->compareWithSnapshot();
if ($result['changed']) {
echo "設定変更が検出されました。\n";
foreach ($result['changes'] as $change) {
echo " {$change['directive']}: {$change['old_value']} → {$change['new_value']}\n";
}
} else {
echo "設定変更はありませんでした。\n";
}
} catch (RuntimeException $e) {
echo "エラー: " . $e->getMessage() . "\n";
}
break;
case 'monitor':
$interval = isset($argv[2]) ? (int)$argv[2] : 300;
$monitor->startMonitoring($interval);
break;
case 'report':
echo $monitor->generateConfigReport();
break;
default:
echo "使用方法:\n";
echo " php opcache-monitor.php snapshot - 現在の設定のスナップショット取得\n";
echo " php opcache-monitor.php compare - スナップショットとの比較\n";
echo " php opcache-monitor.php monitor [間隔] - リアルタイム監視開始\n";
echo " php opcache-monitor.php report - 設定レポート生成\n";
}
}
?>
設定の最適化ガイド
1. 用途別推奨設定
<?php
class OpcacheOptimizationGuide {
public static function getRecommendedSettings($environment, $applicationSize = 'medium') {
echo "=== {$environment} 環境の推奨設定 ({$applicationSize} サイズ) ===\n\n";
$settings = self::generateSettings($environment, $applicationSize);
echo "php.ini 設定:\n";
foreach ($settings as $directive => $value) {
echo "{$directive}={$value}\n";
}
echo "\n解説:\n";
self::explainSettings($environment, $settings);
return $settings;
}
private static function generateSettings($environment, $size) {
$baseSettings = [
'opcache.enable' => 1,
'opcache.enable_cli' => 0,
'opcache.memory_consumption' => 128,
'opcache.interned_strings_buffer' => 8,
'opcache.max_accelerated_files' => 4000,
'opcache.revalidate_freq' => 2,
'opcache.fast_shutdown' => 0,
'opcache.enable_file_override' => 0,
'opcache.optimization_level' => '0x7FFFBFFF',
'opcache.inherited_hack' => 1,
'opcache.dups_fix' => 0,
'opcache.blacklist_filename' => ''
];
// 環境別調整
switch ($environment) {
case 'development':
$baseSettings['opcache.enable_cli'] = 1;
$baseSettings['opcache.validate_timestamps'] = 1;
$baseSettings['opcache.revalidate_freq'] = 2;
$baseSettings['opcache.save_comments'] = 1;
$baseSettings['opcache.load_comments'] = 1;
$baseSettings['opcache.enable_file_override'] = 0;
$baseSettings['opcache.optimization_level'] = '0x7FFFBFFF';
$baseSettings['opcache.file_update_protection'] = 2;
$baseSettings['opcache.max_wasted_percentage'] = 10;
break;
case 'testing':
case 'staging':
$baseSettings['opcache.validate_timestamps'] = 1;
$baseSettings['opcache.revalidate_freq'] = 60;
$baseSettings['opcache.save_comments'] = 1;
$baseSettings['opcache.load_comments'] = 1;
$baseSettings['opcache.enable_file_override'] = 1;
$baseSettings['opcache.file_update_protection'] = 2;
$baseSettings['opcache.max_wasted_percentage'] = 5;
break;
case 'production':
$baseSettings['opcache.validate_timestamps'] = 0;
$baseSettings['opcache.revalidate_freq'] = 0;
$baseSettings['opcache.save_comments'] = 0;
$baseSettings['opcache.load_comments'] = 0;
$baseSettings['opcache.enable_file_override'] = 1;
$baseSettings['opcache.file_update_protection'] = 2;
$baseSettings['opcache.max_wasted_percentage'] = 5;
break;
}
// サイズ別調整
switch ($size) {
case 'small':
$baseSettings['opcache.memory_consumption'] = 64;
$baseSettings['opcache.interned_strings_buffer'] = 4;
$baseSettings['opcache.max_accelerated_files'] = 2000;
break;
case 'medium':
$baseSettings['opcache.memory_consumption'] = 128;
$baseSettings['opcache.interned_strings_buffer'] = 8;
$baseSettings['opcache.max_accelerated_files'] = 4000;
break;
case 'large':
$baseSettings['opcache.memory_consumption'] = 256;
$baseSettings['opcache.interned_strings_buffer'] = 16;
$baseSettings['opcache.max_accelerated_files'] = 10000;
break;
case 'enterprise':
$baseSettings['opcache.memory_consumption'] = 512;
$baseSettings['opcache.interned_strings_buffer'] = 32;
$baseSettings['opcache.max_accelerated_files'] = 20000;
break;
}
return $baseSettings;
}
private static function explainSettings($environment, $settings) {
$explanations = [
'opcache.enable' => 'OPcacheを有効にします',
'opcache.enable_cli' => 'CLI環境でのOPcache利用設定',
'opcache.memory_consumption' => 'OPcacheが使用するメモリ量(MB)',
'opcache.interned_strings_buffer' => '文字列格納用バッファサイズ(MB)',
'opcache.max_accelerated_files' => 'キャッシュ可能な最大ファイル数',
'opcache.validate_timestamps' => 'ファイルのタイムスタンプを検証するか',
'opcache.revalidate_freq' => 'タイムスタンプの再検証頻度(秒)',
'opcache.save_comments' => 'コメントをキャッシュに保存するか',
'opcache.enable_file_override' => 'file_exists()等の関数を最適化するか',
'opcache.max_wasted_percentage' => '無駄領域の最大割合(%)'
];
foreach ($settings as $directive => $value) {
if (isset($explanations[$directive])) {
echo " {$directive}: {$explanations[$directive]}\n";
}
}
// 環境別の注意点
echo "\n注意点:\n";
switch ($environment) {
case 'development':
echo " - タイムスタンプ検証を有効にして、ファイル変更をすぐ反映\n";
echo " - コメント保存を有効にして、IDE等での開発支援機能を維持\n";
echo " - CLIでもOPcacheを有効にして、コマンドライン作業を高速化\n";
break;
case 'production':
echo " - タイムスタンプ検証を無効にして最高のパフォーマンスを実現\n";
echo " - コメント保存を無効にしてメモリを節約\n";
echo " - ファイル関数の最適化を有効にして I/O を削減\n";
break;
}
}
public static function benchmarkSettings($settingsArray) {
echo "=== 設定別パフォーマンステスト ===\n\n";
foreach ($settingsArray as $name => $settings) {
echo "テスト対象: {$name}\n";
// 実際のベンチマークは複雑なため、概念的な例を示す
$score = self::calculatePerformanceScore($settings);
echo " パフォーマンススコア: {$score}/100\n";
echo " メモリ効率: " . self::calculateMemoryEfficiency($settings) . "%\n";
echo " 開発適合性: " . self::calculateDevelopmentFriendliness($settings) . "%\n\n";
}
}
private static function calculatePerformanceScore($settings) {
$score = 50; // ベーススコア
// メモリ設定によるスコア調整
$memory = $settings['opcache.memory_consumption'];
if ($memory >= 256) $score += 20;
elseif ($memory >= 128) $score += 15;
elseif ($memory >= 64) $score += 10;
// タイムスタンプ検証の影響
if (!$settings['opcache.validate_timestamps']) $score += 15;
// その他の最適化設定
if ($settings['opcache.enable_file_override']) $score += 10;
if (!$settings['opcache.save_comments']) $score += 5;
return min(100, $score);
}
private static function calculateMemoryEfficiency($settings) {
$efficiency = 70; // ベース効率
$memory = $settings['opcache.memory_consumption'];
$stringBuffer = $settings['opcache.interned_strings_buffer'];
// メモリとバッファのバランス
$ratio = $stringBuffer / $memory;
if ($ratio >= 0.06 && $ratio <= 0.125) $efficiency += 20; // 適切な比率
// 無駄領域の設定
if ($settings['opcache.max_wasted_percentage'] <= 5) $efficiency += 10;
return min(100, $efficiency);
}
private static function calculateDevelopmentFriendliness($settings) {
$friendliness = 30; // ベース値
// 開発に有用な設定
if ($settings['opcache.validate_timestamps']) $friendliness += 25;
if ($settings['opcache.save_comments']) $friendliness += 25;
if ($settings['opcache.enable_cli']) $friendliness += 20;
return min(100, $friendliness);
}
}
// 使用例
$environments = ['development', 'staging', 'production'];
$sizes = ['small', 'medium', 'large'];
foreach ($environments as $env) {
foreach ($sizes as $size) {
OpcacheOptimizationGuide::getRecommendedSettings($env, $size);
echo "\n" . str_repeat("-", 50) . "\n\n";
}
}
?>
まとめ
opcache_get_configuration
関数は、OPcacheの現在の設定を詳細に把握し、最適化を行うための重要なツールです。
主な活用場面:
- 設定の確認と診断: 現在の設定値の確認と問題の特定
- 環境間の設定比較: 開発・ステージング・本番環境の設定統一性確認
- パフォーマンス最適化: アプリケーションに最適な設定値の決定
- 監視と運用: 設定変更の検出と影響評価
重要なポイント:
- 環境に応じた適切な設定を選択する
- 定期的な設定見直しとパフォーマンス測定を行う
- 設定変更の影響を事前に評価する
- 開発効率と本番パフォーマンスのバランスを考慮する
関連する関数
opcache_get_status()
: OPcacheの動作状況を取得opcache_compile_file()
: ファイルを事前コンパイルopcache_reset()
: OPcacheをリセットopcache_invalidate()
: 特定ファイルのキャッシュを無効化ini_get()
: PHP設定値を取得
これらの関数とopcache_get_configuration
を組み合わせることで、OPcacheを完全に制御し、PHPアプリケーションのパフォーマンスを最大限に引き出すことができます。