[PHP]realpath_cache_size関数の使い方を徹底解説!キャッシュサイズの最適化

PHP

はじめに

PHPアプリケーションのパフォーマンスを向上させるには、ファイルシステムアクセスの最適化が欠かせません。PHPは内部的にファイルパスの解決結果をキャッシュしており、このキャッシュのサイズを把握することが重要です。

realpath_cache_size関数を使うと、現在使用されているrealpathキャッシュのサイズを確認でき、適切な設定値を決定できます。この記事では、realpath_cache_size関数の使い方から、実践的なキャッシュサイズの最適化方法まで、詳しく解説していきます。

realpath_cache_size関数とは?

realpath_cache_size関数は、現在使用されているrealpathキャッシュのサイズをバイト単位で取得する関数です。キャッシュがどれだけのメモリを消費しているかを確認できます。

基本的な構文

<?php
realpath_cache_size(): int
?>
  • 引数: なし
  • 戻り値: 使用中のキャッシュサイズ(バイト単位)

最もシンプルな使用例

<?php
$size = realpath_cache_size();
echo "使用中のキャッシュサイズ: {$size} バイト\n";

// 読みやすく変換
$sizeMB = round($size / 1024 / 1024, 2);
echo "使用中のキャッシュサイズ: {$sizeMB} MB\n";
?>

realpathキャッシュサイズの重要性

なぜキャッシュサイズが重要なのか?

  1. パフォーマンスへの影響: キャッシュサイズが小さすぎると、頻繁にキャッシュが破棄され、ファイルシステムへのアクセスが増加します
  2. メモリ使用量: 大きすぎる設定は無駄なメモリ消費につながります
  3. 最適化の指標: 現在の使用量を知ることで、適切な設定値を決定できます

キャッシュサイズの確認方法

<?php
function getCacheSizeInfo() {
    $usedSize = realpath_cache_size();
    $maxSize = ini_get('realpath_cache_size');
    
    // 最大サイズをバイトに変換
    $maxSizeBytes = parseSize($maxSize);
    
    // 使用率を計算
    $usage = ($usedSize / $maxSizeBytes) * 100;
    
    return [
        'used_bytes' => $usedSize,
        'used_formatted' => formatBytes($usedSize),
        'max_size' => $maxSize,
        'max_bytes' => $maxSizeBytes,
        'max_formatted' => formatBytes($maxSizeBytes),
        'usage_percent' => round($usage, 2),
        'available_bytes' => $maxSizeBytes - $usedSize,
        'available_formatted' => formatBytes($maxSizeBytes - $usedSize)
    ];
}

function parseSize($size) {
    $unit = strtolower(substr($size, -1));
    $value = (int)$size;
    
    switch ($unit) {
        case 'g': return $value * 1024 * 1024 * 1024;
        case 'm': return $value * 1024 * 1024;
        case 'k': return $value * 1024;
        default: return $value;
    }
}

function formatBytes($bytes) {
    $units = ['B', 'KB', 'MB', 'GB'];
    $i = 0;
    
    while ($bytes >= 1024 && $i < count($units) - 1) {
        $bytes /= 1024;
        $i++;
    }
    
    return round($bytes, 2) . ' ' . $units[$i];
}

// 使用例
$info = getCacheSizeInfo();
echo "=== realpathキャッシュ情報 ===\n";
echo "使用中: {$info['used_formatted']}\n";
echo "最大サイズ: {$info['max_formatted']}\n";
echo "使用率: {$info['usage_percent']}%\n";
echo "空き容量: {$info['available_formatted']}\n";
?>

実践的な使用例

1. キャッシュサイズのモニタリング

<?php
class CacheSizeMonitor {
    private $threshold;
    
    public function __construct($warningThreshold = 80, $criticalThreshold = 90) {
        $this->warningThreshold = $warningThreshold;
        $this->criticalThreshold = $criticalThreshold;
    }
    
    public function check() {
        $usedSize = realpath_cache_size();
        $maxSize = parseSize(ini_get('realpath_cache_size'));
        $usage = ($usedSize / $maxSize) * 100;
        
        $status = 'ok';
        $message = 'キャッシュサイズは正常です';
        
        if ($usage >= $this->criticalThreshold) {
            $status = 'critical';
            $message = sprintf(
                'キャッシュ使用率が危険レベル: %.2f%% (%s / %s)',
                $usage,
                formatBytes($usedSize),
                formatBytes($maxSize)
            );
        } elseif ($usage >= $this->warningThreshold) {
            $status = 'warning';
            $message = sprintf(
                'キャッシュ使用率が高い: %.2f%% (%s / %s)',
                $usage,
                formatBytes($usedSize),
                formatBytes($maxSize)
            );
        }
        
        return [
            'status' => $status,
            'usage_percent' => round($usage, 2),
            'used_size' => $usedSize,
            'max_size' => $maxSize,
            'message' => $message
        ];
    }
    
    public function log() {
        $result = $this->check();
        
        $logEntry = sprintf(
            "[%s] %s - Status: %s, Usage: %.2f%%\n",
            date('Y-m-d H:i:s'),
            $result['message'],
            $result['status'],
            $result['usage_percent']
        );
        
        error_log($logEntry);
        
        return $result;
    }
}

// 使用例
$monitor = new CacheSizeMonitor();
$result = $monitor->check();

echo $result['message'] . "\n";

if ($result['status'] !== 'ok') {
    echo "⚠ アクション推奨: realpath_cache_sizeの増加を検討してください\n";
}
?>

2. アプリケーション起動時のキャッシュサイズチェック

<?php
/**
 * アプリケーション起動時にキャッシュサイズをチェック
 */
function checkCacheOnStartup() {
    $usedSize = realpath_cache_size();
    $maxSize = parseSize(ini_get('realpath_cache_size'));
    $usage = ($usedSize / $maxSize) * 100;
    
    // ログに記録
    $logData = [
        'timestamp' => date('Y-m-d H:i:s'),
        'used_size' => formatBytes($usedSize),
        'max_size' => formatBytes($maxSize),
        'usage_percent' => round($usage, 2),
        'entries' => count(realpath_cache_get())
    ];
    
    error_log('Realpath Cache Startup: ' . json_encode($logData));
    
    // 警告閾値を超えている場合
    if ($usage > 80) {
        trigger_error(
            sprintf(
                'Realpath cache usage is high: %.2f%% (%s / %s)',
                $usage,
                formatBytes($usedSize),
                formatBytes($maxSize)
            ),
            E_USER_WARNING
        );
    }
    
    return $logData;
}

// アプリケーション起動時に実行
checkCacheOnStartup();
?>

3. キャッシュサイズの推移を追跡

<?php
class CacheSizeTracker {
    private $dataFile;
    
    public function __construct($dataFile = '/tmp/cache_size_history.json') {
        $this->dataFile = $dataFile;
    }
    
    public function record() {
        $currentSize = realpath_cache_size();
        $maxSize = parseSize(ini_get('realpath_cache_size'));
        
        $data = $this->loadHistory();
        
        $data[] = [
            'timestamp' => time(),
            'datetime' => date('Y-m-d H:i:s'),
            'size' => $currentSize,
            'max_size' => $maxSize,
            'usage_percent' => round(($currentSize / $maxSize) * 100, 2),
            'entries' => count(realpath_cache_get())
        ];
        
        // 最新1000件のみ保持
        if (count($data) > 1000) {
            $data = array_slice($data, -1000);
        }
        
        $this->saveHistory($data);
    }
    
    public function getStats($hours = 24) {
        $data = $this->loadHistory();
        $cutoff = time() - ($hours * 3600);
        
        // 指定時間内のデータのみフィルタ
        $recentData = array_filter($data, function($entry) use ($cutoff) {
            return $entry['timestamp'] >= $cutoff;
        });
        
        if (empty($recentData)) {
            return null;
        }
        
        $sizes = array_column($recentData, 'size');
        $usages = array_column($recentData, 'usage_percent');
        
        return [
            'period_hours' => $hours,
            'samples' => count($recentData),
            'size_min' => formatBytes(min($sizes)),
            'size_max' => formatBytes(max($sizes)),
            'size_avg' => formatBytes(array_sum($sizes) / count($sizes)),
            'usage_min' => round(min($usages), 2),
            'usage_max' => round(max($usages), 2),
            'usage_avg' => round(array_sum($usages) / count($usages), 2),
            'current_size' => formatBytes(end($recentData)['size']),
            'current_usage' => end($recentData)['usage_percent']
        ];
    }
    
    private function loadHistory() {
        if (!file_exists($this->dataFile)) {
            return [];
        }
        
        $json = file_get_contents($this->dataFile);
        return json_decode($json, true) ?: [];
    }
    
    private function saveHistory($data) {
        file_put_contents($this->dataFile, json_encode($data));
    }
}

// 使用例
$tracker = new CacheSizeTracker();

// 定期的に実行(cronなど)
$tracker->record();

// 統計情報の取得
$stats = $tracker->getStats(24);
if ($stats) {
    echo "=== 過去24時間の統計 ===\n";
    echo "サンプル数: {$stats['samples']}\n";
    echo "最小サイズ: {$stats['size_min']}\n";
    echo "最大サイズ: {$stats['size_max']}\n";
    echo "平均サイズ: {$stats['size_avg']}\n";
    echo "平均使用率: {$stats['usage_avg']}%\n";
}
?>

4. リアルタイムダッシュボード

<?php
/**
 * キャッシュサイズのリアルタイムダッシュボード
 */
function displayCacheDashboard() {
    $usedSize = realpath_cache_size();
    $cache = realpath_cache_get();
    $maxSize = parseSize(ini_get('realpath_cache_size'));
    $ttl = ini_get('realpath_cache_ttl');
    
    $usage = ($usedSize / $maxSize) * 100;
    $entryCount = count($cache);
    $avgEntrySize = $entryCount > 0 ? $usedSize / $entryCount : 0;
    
    // 統計情報
    $fileCount = 0;
    $dirCount = 0;
    foreach ($cache as $entry) {
        if ($entry['is_dir']) {
            $dirCount++;
        } else {
            $fileCount++;
        }
    }
    
    echo "╔════════════════════════════════════════════════╗\n";
    echo "║     Realpath Cache ダッシュボード              ║\n";
    echo "╠════════════════════════════════════════════════╣\n";
    printf("║ 使用サイズ: %-35s║\n", formatBytes($usedSize));
    printf("║ 最大サイズ: %-35s║\n", formatBytes($maxSize));
    printf("║ 使用率: %-39s║\n", sprintf("%.2f%%", $usage));
    echo "╠════════════════════════════════════════════════╣\n";
    printf("║ 総エントリ数: %-32d║\n", $entryCount);
    printf("║ ファイル: %-36d║\n", $fileCount);
    printf("║ ディレクトリ: %-32d║\n", $dirCount);
    printf("║ エントリ平均サイズ: %-27s║\n", formatBytes($avgEntrySize));
    echo "╠════════════════════════════════════════════════╣\n";
    printf("║ TTL: %-42d║\n", $ttl);
    printf("║ 空き容量: %-36s║\n", formatBytes($maxSize - $usedSize));
    echo "╠════════════════════════════════════════════════╣\n";
    
    // ステータス表示
    if ($usage >= 90) {
        echo "║ ステータス: 🔴 危険 - 即座の対応が必要        ║\n";
    } elseif ($usage >= 80) {
        echo "║ ステータス: 🟡 警告 - サイズ増加を検討        ║\n";
    } elseif ($usage >= 70) {
        echo "║ ステータス: 🟢 注意 - モニタリング継続        ║\n";
    } else {
        echo "║ ステータス: ✅ 正常                            ║\n";
    }
    
    echo "╚════════════════════════════════════════════════╝\n";
}

// 使用例
displayCacheDashboard();
?>

5. 自動アラートシステム

<?php
class CacheSizeAlertSystem {
    private $config;
    
    public function __construct($config = []) {
        $this->config = array_merge([
            'warning_threshold' => 80,
            'critical_threshold' => 90,
            'alert_cooldown' => 3600, // 1時間
            'state_file' => '/tmp/cache_alert_state.json'
        ], $config);
    }
    
    public function checkAndAlert() {
        $usedSize = realpath_cache_size();
        $maxSize = parseSize(ini_get('realpath_cache_size'));
        $usage = ($usedSize / $maxSize) * 100;
        
        $state = $this->loadState();
        $now = time();
        
        // アラートレベルの判定
        $level = null;
        if ($usage >= $this->config['critical_threshold']) {
            $level = 'critical';
        } elseif ($usage >= $this->config['warning_threshold']) {
            $level = 'warning';
        }
        
        // アラートが必要かチェック
        if ($level && $this->shouldAlert($level, $state, $now)) {
            $this->sendAlert($level, $usage, $usedSize, $maxSize);
            $this->updateState($level, $now);
        }
        
        return [
            'level' => $level,
            'usage' => round($usage, 2),
            'alerted' => $level !== null
        ];
    }
    
    private function shouldAlert($level, $state, $now) {
        if (!isset($state['last_alert'][$level])) {
            return true;
        }
        
        $lastAlert = $state['last_alert'][$level];
        return ($now - $lastAlert) >= $this->config['alert_cooldown'];
    }
    
    private function sendAlert($level, $usage, $usedSize, $maxSize) {
        $message = sprintf(
            "[%s] Realpath Cache Alert: %s\n" .
            "使用率: %.2f%%\n" .
            "使用サイズ: %s / %s\n" .
            "推奨アクション: realpath_cache_sizeを増やしてください\n",
            strtoupper($level),
            $level === 'critical' ? '緊急' : '警告',
            $usage,
            formatBytes($usedSize),
            formatBytes($maxSize)
        );
        
        // ログに記録
        error_log($message);
        
        // メール送信やSlack通知など(実装例)
        // $this->sendEmail($message);
        // $this->sendSlackNotification($message);
        
        echo $message;
    }
    
    private function loadState() {
        if (!file_exists($this->config['state_file'])) {
            return ['last_alert' => []];
        }
        
        $json = file_get_contents($this->config['state_file']);
        return json_decode($json, true) ?: ['last_alert' => []];
    }
    
    private function updateState($level, $timestamp) {
        $state = $this->loadState();
        $state['last_alert'][$level] = $timestamp;
        file_put_contents($this->config['state_file'], json_encode($state));
    }
}

// 使用例(cronで定期実行)
$alertSystem = new CacheSizeAlertSystem([
    'warning_threshold' => 75,
    'critical_threshold' => 85
]);

$result = $alertSystem->checkAndAlert();
echo "チェック完了 - レベル: " . ($result['level'] ?? 'なし') . "\n";
?>

6. パフォーマンステスト

<?php
/**
 * キャッシュサイズがパフォーマンスに与える影響をテスト
 */
class CacheSizePerformanceTest {
    public function run($iterations = 1000) {
        echo "=== キャッシュパフォーマンステスト ===\n\n";
        
        // テスト前の状態
        $beforeSize = realpath_cache_size();
        $beforeEntries = count(realpath_cache_get());
        
        echo "開始時のキャッシュサイズ: " . formatBytes($beforeSize) . "\n";
        echo "開始時のエントリ数: {$beforeEntries}\n\n";
        
        // テスト実行
        $startTime = microtime(true);
        
        for ($i = 0; $i < $iterations; $i++) {
            // ファイル操作をシミュレート
            $path = __DIR__ . '/test_' . ($i % 100) . '.php';
            @realpath($path);
            @file_exists($path);
        }
        
        $endTime = microtime(true);
        $duration = $endTime - $startTime;
        
        // テスト後の状態
        $afterSize = realpath_cache_size();
        $afterEntries = count(realpath_cache_get());
        
        echo "テスト完了\n";
        echo "実行時間: " . round($duration * 1000, 2) . " ms\n";
        echo "操作数: {$iterations}\n";
        echo "平均処理時間: " . round(($duration / $iterations) * 1000000, 2) . " μs\n\n";
        
        echo "終了時のキャッシュサイズ: " . formatBytes($afterSize) . "\n";
        echo "終了時のエントリ数: {$afterEntries}\n\n";
        
        $sizeIncrease = $afterSize - $beforeSize;
        $entryIncrease = $afterEntries - $beforeEntries;
        
        echo "サイズ増加: " . formatBytes($sizeIncrease) . "\n";
        echo "エントリ増加: {$entryIncrease}\n";
        
        if ($entryIncrease > 0) {
            $avgEntrySize = $sizeIncrease / $entryIncrease;
            echo "エントリ平均サイズ: " . formatBytes($avgEntrySize) . "\n";
        }
    }
}

// 使用例
$test = new CacheSizePerformanceTest();
$test->run(1000);
?>

最適なキャッシュサイズの決定

サイズ決定のガイドライン

<?php
function recommendCacheSize() {
    // 現在の使用状況を確認
    $currentSize = realpath_cache_size();
    $currentEntries = count(realpath_cache_get());
    $currentMax = parseSize(ini_get('realpath_cache_size'));
    
    // 使用率を計算
    $usage = ($currentSize / $currentMax) * 100;
    
    echo "=== キャッシュサイズ推奨設定 ===\n\n";
    echo "現在の設定\n";
    echo "  最大サイズ: " . formatBytes($currentMax) . "\n";
    echo "  使用サイズ: " . formatBytes($currentSize) . "\n";
    echo "  使用率: " . round($usage, 2) . "%\n";
    echo "  エントリ数: {$currentEntries}\n\n";
    
    // 推奨サイズの計算
    $recommendedSize = $currentSize * 1.5; // 現在の1.5倍
    
    // 最小値と最大値の制限
    $minSize = 4 * 1024 * 1024;    // 最小4MB
    $maxSize = 256 * 1024 * 1024;  // 最大256MB
    
    if ($recommendedSize < $minSize) {
        $recommendedSize = $minSize;
    } elseif ($recommendedSize > $maxSize) {
        $recommendedSize = $maxSize;
    }
    
    $recommendedSizeMB = ceil($recommendedSize / 1024 / 1024);
    
    echo "推奨設定\n";
    echo "  realpath_cache_size = {$recommendedSizeMB}M\n\n";
    
    // 設定方法の説明
    echo "設定方法:\n";
    echo "1. php.iniに追加:\n";
    echo "   realpath_cache_size = {$recommendedSizeMB}M\n\n";
    echo "2. php-fpmの場合 (pool設定):\n";
    echo "   php_admin_value[realpath_cache_size] = {$recommendedSizeMB}M\n\n";
    
    // アプリケーションタイプ別の推奨値
    echo "アプリケーションタイプ別の推奨値:\n";
    echo "  小規模アプリ: 4M - 8M\n";
    echo "  中規模アプリ: 16M - 32M\n";
    echo "  大規模アプリ: 64M - 128M\n";
    echo "  超大規模アプリ: 128M - 256M\n";
}

recommendCacheSize();
?>

まとめ

realpath_cache_size関数のポイントをおさらいしましょう:

  1. 現在使用中のキャッシュサイズをバイト単位で取得
  2. キャッシュ使用率の監視に不可欠
  3. パフォーマンス最適化の重要な指標
  4. 使用率が80%を超えたら設定の見直しが必要
  5. 定期的なモニタリングでパフォーマンスを維持
  6. アプリケーション規模に応じた適切なサイズ設定が重要
  7. realpath_cache_get()と組み合わせて詳細分析

realpathキャッシュのサイズを適切に管理することで、PHPアプリケーションのパフォーマンスを大幅に向上させることができます。realpath_cache_size関数を活用して、最適な設定を見つけましょう!

参考リンク


この記事が役に立ったら、ぜひシェアしてください!PHPに関する他の記事もお楽しみに。

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