PHP Note
category: 実験・実測 値の受け渡し 文字列連結どれが速い?

ファイル形式別読み込み速度比較

created: 2009-03-15 | modified: 2009-03-15

データファイルのフォーマットは何がいい?

久しぶりのパフォーマンス比較シリーズ(?)です。テキスト形式のファイルにはよくお世話になります。設定ファイルなど一度読み込めば済むものはパフォーマンスが気になることはありませんが、アクセスログなどデータが多い場合、どんなフォーマットにしておけばサクサク動いてくれるのか気になったので確かめてみました。


データのフォーマット

比較したフォーマットは、PHPスクリプト、INI形式、Serializeデータ、XML形式、CSV形式 の5つです。以下は PHPで書いたアクセスログ1000件分の一部で、他の形式についてもまったく同じ内容をそれぞれの書式に直したファイルを使いました。

<?php
/**
 * PHPスクリプトのログデータ
 */
$params = array (
    // 一件分のログ
    0 => array (
        'date' => '2009-03-15',
        'time' => '17:03:41',
        'user' => '',
        'host' => '192.168.0.11',
        'server' => 'localhost',
        'method' => 'GET',
        'protocol' => 'HTTP/1.1',
        'request' => '/test/example2.php',
        'referer' => 'http://localhost/test/example.php?q=PHP+session',
        'agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6',
    ),
 
    // 上記の形式で合計1,000件分
            .
            .
            .
);

テスト環境とスクリプト

プログラムで扱えるデータにした後ファイル形式は無関係なので、ファイルを読み込みプログラムで利用可能なデータにするまで、を比べることにしました。

環境は自宅の Win2000Pro SP4 に載せてる Apache2.0.63 + PHP5.2.9 です。XMLの読み込みついては、PHP5に標準搭載の SimpleXML を用いました。このサイトは SimpleXML が無い PHP4 なので今回は自宅PCでのみで測定です。

<?php
// データファイルのパス
$dir = 'D:/home/localhost/logs/';
$file1 = $dir.'log.php';  // 1. PHPフォーマット
$file2 = $dir.'log.ini';  // 2. INIフォーマット
$file3 = $dir.'log.dat';  // 3. Serializeフォーマット
$file4 = $dir.'log.xml';  // 4. XMLフォーマット
$file5 = $dir.'log.csv';  // 5. CSVフォーマット
 
// 繰り返し回数
$loop = 5;
 
/**
 * 各ファイルの読み込み処理
 */
// 1. PHPフォーマット
function loadPhp ( $file ) {
    include $file;
    return $params;
}
 
// 2. INIフォーマット
function loadIni ( $file ) {
    return parse_ini_file($file, true);
}
 
// 3. Serializeフォーマット
function loadSerialize ( $file ) {
    $params = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    foreach ($params as $key => $val) 
        $params[$key] = unserialize($val);
    return $params;
}
 
// 4. XMLフォーマット
function loadXml ( $file ) {
    return simplexml_load_file($file);
}
 
// 5. CSVフォーマット
function loadCsv ( $file ) {
    $params = array();
    $fp = fopen($file, 'r');
    while(false === feof($fp))
        $params[] = fgetcsv($fp);
    fclose($fp);
    return $params;
}

/**
 * 処理速度測定
 */
// 1. PHPフォーマット
$time1 = microtime(true);
for ($c = 0; $c < $loop; $c++)
    $data = loadPhp($file1);
$time1 = microtime(true) - $time1;
 
// 2. INIフォーマット
$time2 = microtime(true);
for ($c = 0; $c < $loop; $c++)
    $data = loadIni($file2);
$time2 = microtime(true) - $time2;
 
// 3. Serializeフォーマット
$time3 = microtime(true);
for ($c = 0; $c < $loop; $c++)
    $data = loadSerialize($file3);
$time3 = microtime(true) - $time3;
 
// 4. XMLフォーマット
$time4 = microtime(true);
for ($c = 0; $c < $loop; $c++)
    $data = loadXml($file4);
$time4 = microtime(true) - $time4;
 
// 5. CSVフォーマット
$time5 = microtime(true);
for ($c = 0; $c < $loop; $c++)
    $data = loadCsv($file5);
$time5 = microtime(true) - $time5;
 
/**
 * 結果表示
 */
?>
<p><?php echo sprintf('%.4f', $time1); ?> : 1. PHP</p>
<p><?php echo sprintf('%.4f', $time2); ?> : 2. INI</p>
<p><?php echo sprintf('%.4f', $time3); ?> : 3. Serialize</p>
<p><?php echo sprintf('%.4f', $time4); ?> : 4. XML</p>
<p><?php echo sprintf('%.4f', $time5); ?> : 5. CSV</p>

測定結果

先のスクリプトを5回実行した結果と平均値(Ave)です。

           Ave      1       2       3       4       5
PHP        0.66792  0.6499  0.6859  0.6838  0.6796  0.6404
INI        0.59386  0.6065  0.5809  0.5715  0.6078  0.6026
Serialize  0.31736  0.3103  0.3291  0.3274  0.3115  0.3085
XML        0.70126  0.7161  0.6937  0.6927  0.7239  0.6799
CSV        0.78802  0.7729  0.7829  0.8124  0.7799  0.7920

読み込んでからの加工が無い分PHPスクリプトが一番速いだろうと思ってたのですがそうでもありませんでした。Serialize の圧勝です。PHPの場合はファイルを読み込んでからデータとなる間に構文チェックが入るのがこの要因となってるのでしょう。

まとまったデータの再利用が想定されるならば 「serialize したものをキャッシュファイルに保存して unserialize で復元する」この手法が適しているようです。

他の形式にしても 一旦 serialize しファイルに保存したものを再利用すれば、パフォーマンスの改善が見込めそうです。

アクセス解析のスクリプトを考えてたところなので、ログの保存形式は serialize でやってみようと思います。

category: 実験・実測 値の受け渡し 文字列連結どれが速い?
PHP Note
ページの一番上へ
Googleグックマークに登録 Yahooグックマークに登録 livedoorクリップに登録 @niftyクリップに登録 はてなブックマークに登録 deliciousに登録 Buzzurlに登録 FC2ブックマークに登録
最近更新したNote
よく読まれている記事
Yahoo Search

最近更新された掲示板トピックス
PHPマニュアル
今日のブックマーク
PHPマニュアル関数検索
関数名を入力し検索ボタンをクリック↑