【PHP】メモリ使用量と処理時間を計測しながらボトルネックを特定する方法

【PHP】メモリ使用量と処理時間を計測しながらボトルネックを特定する方法 PHP

PHPスクリプトのパフォーマンスを最適化するには、どこに処理の負荷がかかっているのかを正確に把握する必要があります。本記事では、メモリ使用量と処理時間をリアルタイムで計測しながら、ボトルネックを特定する具体的な方法について解説します。

実行時間の計測方法

まずは、処理にかかる時間を測定する方法から紹介します。マイクロ秒単位での計測には、microtime(true)関数を使うのが一般的です。

$start = microtime(true);

// 処理対象のコード
usleep(500000); // 0.5秒待機

$end = microtime(true);
$executionTime = $end - $start;

echo "実行時間:{$executionTime} 秒";

microtime(true)はUNIXタイムスタンプ(float型)を返すため、$end - $startで秒単位の経過時間を取得できます。

メモリ使用量の計測方法

次に、スクリプト実行中に使用されたメモリ量を計測するには、memory_get_usage()またはmemory_get_peak_usage()関数を使用します。

$startMemory = memory_get_usage();

// メモリを消費する処理
$array = range(1, 100000);

$endMemory = memory_get_usage();
$usedMemory = $endMemory - $startMemory;

echo "使用メモリ:{$usedMemory} バイト";

memory_get_usage()はスクリプトが現在使用しているメモリ量を返し、memory_get_peak_usage()は最大使用量を返します。後者はピークメモリを追跡したいときに便利です。

処理単位でのパフォーマンスを比較する

複数の処理ブロックごとに計測を行えば、どの処理に時間やメモリがかかっているかを比較できます。

$start1 = microtime(true);
$arr1 = range(1, 1000000);
$end1 = microtime(true);

$start2 = microtime(true);
$arr2 = [];
for ($i = 1; $i <= 1000000; $i++) {
  $arr2[] = $i;
}
$end2 = microtime(true);

echo "range関数:".($end1 - $start1)." 秒\n";
echo "for文:".($end2 - $start2)." 秒\n";

このようにすると、処理方法の違いによるパフォーマンス差を明確に比較することができます。

ボトルネック特定のためのログ出力例

ボトルネックを後から調査するために、処理ポイントごとのログを残すのも有効です。

function log_profile($label)
{
  static $startTime;
  static $startMemory;

  if (!$startTime) {
    $startTime = microtime(true);
    $startMemory = memory_get_usage();
  }

  $currentTime = microtime(true);
  $currentMemory = memory_get_usage();

  $elapsedTime = number_format($currentTime - $startTime, 4);
  $usedMemory = number_format($currentMemory - $startMemory);

  error_log("[{$label}] 経過時間: {$elapsedTime} 秒 / 使用メモリ: {$usedMemory} バイト");
}

// 利用例
log_profile('処理開始');

// 時間がかかる処理
sleep(1);

log_profile('処理1完了');

// メモリを大量に使う処理
$data = array_fill(0, 100000, str_repeat('a', 100));

log_profile('処理2完了');

error_log()を使えば、Webページには出力せずにログファイルに記録できます。これにより、実行環境に負荷をかけずにボトルネックのトレースが可能になります。

本番環境での注意点

  • memory_get_usage()はPHPのヒープ領域全体を測定するため、Apacheなどのオーバーヘッドも含む可能性があります。
  • microtime()を用いたベンチマークは非常に小さい差を測定できる反面、他プロセスの影響を受けやすいので複数回の平均をとるのが望ましいです。
  • 本番環境では、XdebugやBlackfireなどの専用プロファイラの導入も検討してください。

まとめ

PHPのスクリプトでパフォーマンスを向上させるには、メモリ消費量と処理時間を「見える化」することが最も重要です。microtime(true)memory_get_usage()を組み合わせれば、軽量かつ簡易的なプロファイリングが可能です。

手軽な計測から始めて、必要に応じて専用ツールに移行するのが、無理のない最適化の第一歩と言えるでしょう。