2026年5月20日

2026年5月20日

WordPressのOPcacheを最適化する方法

はじめに

OPcacheはPHPスクリプトのコンパイル済みバイトコードをメモリにキャッシュし、リクエストごとのコンパイル処理を省略することでWordPressの実行速度を大幅に向上させます。適切なチューニングにより応答時間を数倍改善できます。

症状・原因

  • WordPress管理画面や記事表示が遅い(OPcacheが無効または設定不足)
  • PHPのOPcacheが有効になっているはずなのに速度が改善されない
  • ファイルを更新しても古いキャッシュが残って変更が反映されない
  • OPcacheのメモリが枯渇してキャッシュが効かなくなっている

解決手順

ステップ1:OPcacheの現在の状態を確認する

# PHP コマンドラインで OPcache 設定を確認
php -i | grep -i opcache

# OPcache が有効か確認
php -r "echo opcache_get_status() ? 'OPcache enabled' : 'OPcache disabled';"

# OPcache の統計情報を確認
php -r "
\$status = opcache_get_status(false);
echo 'Memory used: ' . round(\$status['memory_usage']['used_memory'] / 1024 / 1024, 2) . ' MB' . PHP_EOL;
echo 'Memory free: ' . round(\$status['memory_usage']['free_memory'] / 1024 / 1024, 2) . ' MB' . PHP_EOL;
echo 'Cached scripts: ' . \$status['opcache_statistics']['num_cached_scripts'] . PHP_EOL;
echo 'Cache hits: ' . \$status['opcache_statistics']['hits'] . PHP_EOL;
echo 'Cache misses: ' . \$status['opcache_statistics']['misses'] . PHP_EOL;
echo 'Hit rate: ' . round(\$status['opcache_statistics']['opcache_hit_rate'], 2) . '%' . PHP_EOL;
"
// WordPress 管理画面でOPcacheの状態を確認する簡単なページ
// ※ 一時的なデバッグ用途のみ。本番では削除する

// wp-content/mu-plugins/opcache-status.php(一時的に作成)
if (isset($_GET['opcache_status']) && current_user_can('manage_options')) {
    $status = opcache_get_status(false);
    $config = opcache_get_configuration();

    echo '<pre>';
    echo 'OPcache有効: ' . ($status ? 'YES' : 'NO') . PHP_EOL;
    if ($status) {
        $mem = $status['memory_usage'];
        echo 'メモリ使用: ' . round($mem['used_memory'] / 1024 / 1024, 1) . 'MB / ';
        echo round(($mem['used_memory'] + $mem['free_memory']) / 1024 / 1024, 1) . 'MB' . PHP_EOL;
        echo 'ヒット率: ' . round($status['opcache_statistics']['opcache_hit_rate'], 2) . '%' . PHP_EOL;
        echo 'キャッシュ済みファイル数: ' . $status['opcache_statistics']['num_cached_scripts'] . PHP_EOL;
    }
    echo '</pre>';
    exit;
}

ステップ2:OPcacheの推奨設定を適用する

; php.ini または /etc/php/8.2/mods-available/opcache.ini

[opcache]
; OPcacheを有効化
opcache.enable = 1
opcache.enable_cli = 0  ; CLIでは無効(wp-cliの挙動に影響するため)

; メモリ設定(WordPressの規模に応じて調整)
; 小規模サイト: 64MB / 中規模: 128MB / 大規模: 256MB
opcache.memory_consumption = 128

; 文字列のインターン化用メモリ(MB)
opcache.interned_strings_buffer = 16

; キャッシュするファイルの最大数
; WordPress本体+プラグイン数 × 100 が目安
; find /var/www/html -name "*.php" | wc -l で確認
opcache.max_accelerated_files = 20000

; ファイル変更チェック
; 開発環境: 1(毎回チェック) / 本番: 0(キャッシュ優先)
opcache.validate_timestamps = 0  ; 本番推奨

; ファイル変更チェック間隔(validate_timestamps=1の場合)
opcache.revalidate_freq = 60

; WordPressのアノテーション(@hook等)のために必要
opcache.save_comments = 1

; JIT コンパイル(PHP 8.0以降)
; WordPress での効果は限定的だが有効化推奨
opcache.jit = tracing
opcache.jit_buffer_size = 64M

; 高速シャットダウン
opcache.fast_shutdown = 1

; エラーが発生したファイルをキャッシュしない
opcache.cache_id = ""

ステップ3:PHPファイル数を確認してmax_accelerated_filesを設定する

# WordPress インストール内のPHPファイル数を確認
find /var/www/html -name "*.php" | wc -l

# プラグインごとのPHPファイル数を確認(重いプラグインを特定)
find /var/www/html/wp-content/plugins -name "*.php" | \
    awk -F'/' '{print $8}' | sort | uniq -c | sort -rn | head -20

# 推奨: 確認した数の1.5倍を max_accelerated_files に設定
# 例: 8000ファイルなら opcache.max_accelerated_files = 12000

# 設定変更後にPHP-FPMを再起動
sudo systemctl reload php8.2-fpm

# 設定が反映されたか確認
php -i | grep max_accelerated_files

ステップ4:validate_timestamps=0の場合のキャッシュクリアを自動化する

// functions.php: 本番環境でのOPcacheクリアを自動化

// プラグイン・テーマ更新後に自動クリア
add_action('upgrader_process_complete', function(
    WP_Upgrader $upgrader,
    array $options
): void {
    if (!function_exists('opcache_reset')) return;

    $type = $options['type'] ?? '';
    if (in_array($type, ['plugin', 'theme', 'core'], true)) {
        opcache_reset();
        error_log('OPcache cleared after ' . $type . ' update');
    }
}, 10, 2);

// wp-config.php 保存時にクリア
add_action('update_option', function(string $option): void {
    if (!function_exists('opcache_reset')) return;
    if (in_array($option, ['active_plugins', 'template', 'stylesheet'], true)) {
        opcache_reset();
    }
});

// WP-CLI でクリア
// wp eval "opcache_reset(); echo 'OPcache cleared' . PHP_EOL;"

// デプロイスクリプトでのOPcacheクリア(CI/CD用)
// curl -X POST https://example.com/wp-json/custom/v1/opcache-clear \
//     -H "Authorization: Bearer YOUR_TOKEN"

// REST API エンドポイントでのクリア(デプロイ用)
add_action('rest_api_init', function(): void {
    register_rest_route('custom/v1', '/opcache-clear', [
        'methods'             => 'POST',
        'callback'            => function(): WP_REST_Response {
            if (!function_exists('opcache_reset')) {
                return new WP_REST_Response(['success' => false, 'message' => 'OPcache not available'], 500);
            }
            $result = opcache_reset();
            return new WP_REST_Response(['success' => $result], $result ? 200 : 500);
        },
        'permission_callback' => function(): bool {
            return current_user_can('manage_options');
        },
    ]);
});

ステップ5:OPcacheのヒット率をモニタリングする

// functions.php: OPcacheのヒット率が低い場合に管理者に通知

add_action('admin_notices', function(): void {
    if (!current_user_can('manage_options')) return;
    if (!function_exists('opcache_get_status')) return;

    $status = opcache_get_status(false);
    if (!$status) {
        echo '<div class="notice notice-error"><p>';
        echo '<strong>OPcache が無効です。</strong> php.ini で opcache.enable=1 を設定してください。';
        echo '</p></div>';
        return;
    }

    $hit_rate = $status['opcache_statistics']['opcache_hit_rate'];
    $mem_used = $status['memory_usage']['used_memory'];
    $mem_free = $status['memory_usage']['free_memory'];
    $mem_total = $mem_used + $mem_free;
    $mem_usage_pct = round($mem_used / $mem_total * 100);

    // ヒット率が低い場合
    if ($hit_rate < 90) {
        echo '<div class="notice notice-warning"><p>';
        echo "OPcache ヒット率: <strong>{$hit_rate}%</strong>(目標: 90%以上)。";
        echo 'opcache.max_accelerated_files を増やすことを検討してください。';
        echo '</p></div>';
    }

    // メモリが90%以上使用されている場合
    if ($mem_usage_pct > 90) {
        echo '<div class="notice notice-warning"><p>';
        echo "OPcache メモリ使用率: <strong>{$mem_usage_pct}%</strong>。";
        echo 'opcache.memory_consumption を増やすことを検討してください。';
        echo '</p></div>';
    }
});

注意事項

  • opcache.validate_timestamps = 0 は最高パフォーマンスですが、ファイルを編集しても自動的にキャッシュが更新されません。デプロイ後に必ずopcache_reset()を呼び出してください
  • opcache.enable_cli = 1 にするとWP-CLIの実行時にOPcacheが有効になり、CLIと Web で異なるキャッシュが生成されて予期しない動作になることがあります。enable_cli = 0が推奨です
  • JIT(opcache.jit = tracing)はCPU集約型の処理を高速化しますが、WordPressのI/Oバウンドな処理には効果が限定的です。有効化してベンチマークで改善を確認してから本番適用を検討してください

まとめ

OPcache最適化は①php -r "echo opcache_get_status()..."で現状確認、②memory_consumption=128max_accelerated_files=20000validate_timestamps=0php.iniに設定、③PHPファイル数をfindコマンドで確認してmax_accelerated_filesを調整、④upgrader_process_completeフックで更新時に自動opcache_reset()、⑤管理画面でヒット率をモニタリング、の順で進めます。ヒット率90%以上・メモリ使用率90%以下を目標に調整します。

お気軽にご相談ください

お見積りへ お問い合わせへ