[PHP]opcache_get_configuration関数とは?OPcache設定を取得・解析する完全ガイド

PHP

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アプリケーションのパフォーマンスを最大限に引き出すことができます。

タイトルとURLをコピーしました