1. ホーム
  2. php

[解決済み] PHP の配列を保存するための好ましい方法 (json_encode vs serialize)

2022-03-16 09:14:05

質問

キャッシュ目的で多次元連想配列のデータをフラットファイルに保存する必要があります。時々、ウェブアプリケーションで使用するためにJSONに変換する必要があるかもしれませんが、大部分の時間はPHPで直接その配列を使用することになるでしょう。

このテキストファイルには、配列をJSONとして格納するのと、PHPのシリアライズ配列として格納するのと、どちらが効率的でしょうか?いろいろ調べてみましたが、PHP の最新バージョン (5.3) ではそうなっているようです。 json_decode よりも高速です。 unserialize .

配列はJSONで保存することに傾いています。その方が必要に応じて人間が読みやすく、PHPとJavaScriptの両方でわずかな労力で使用でき、私が読んだところでは、デコードも速いかもしれません(エンコーディングについては不明ですが)。

落とし穴をご存知の方はいらっしゃいますか?どなたか、どちらの方法のパフォーマンス上の利点を示す良いベンチマークをお持ちの方はいらっしゃいますか?

どのように解決するのですか?

優先順位によります。

性能が絶対的な駆動特性であるならば、ぜひとも最速のものを使ってください。 ただ、その違いを十分に理解した上で選択することが大切です。

  • とは異なり serialize() の場合、UTF-8文字をそのままにしておくには、追加のパラメータを追加する必要があります。 json_encode($array, JSON_UNESCAPED_UNICODE) (そうでなければ、UTF-8文字をUnicodeエスケープシーケンスに変換してしまいます)。
  • JSONは、オブジェクトの元のクラスが何であったかを記憶していません(それらは常にstdClassのインスタンスとして復元されます)。
  • を活用することはできません。 __sleep()__wakeup() JSONで
  • デフォルトでは、パブリックプロパティのみがJSONでシリアライズされます。(この場合 PHP>=5.4 を実装することができます。 JsonSerializable でこの動作を変更することができます)。
  • JSONはよりポータブル

そのほかにも、いまは思いつかないような違いがあるかもしれません。

簡単なスピードテストによる比較

<?php

ini_set('display_errors', 1);
error_reporting(E_ALL);

// Make a big, honkin test array
// You may need to adjust this depth to avoid memory limit errors
$testArray = fillArray(0, 5);

// Time json encoding
$start = microtime(true);
json_encode($testArray);
$jsonTime = microtime(true) - $start;
echo "JSON encoded in $jsonTime seconds\n";

// Time serialization
$start = microtime(true);
serialize($testArray);
$serializeTime = microtime(true) - $start;
echo "PHP serialized in $serializeTime seconds\n";

// Compare them
if ($jsonTime < $serializeTime) {
    printf("json_encode() was roughly %01.2f%% faster than serialize()\n", ($serializeTime / $jsonTime - 1) * 100);
}
else if ($serializeTime < $jsonTime ) {
    printf("serialize() was roughly %01.2f%% faster than json_encode()\n", ($jsonTime / $serializeTime - 1) * 100);
} else {
    echo "Impossible!\n";
}

function fillArray( $depth, $max ) {
    static $seed;
    if (is_null($seed)) {
        $seed = array('a', 2, 'c', 4, 'e', 6, 'g', 8, 'i', 10);
    }
    if ($depth < $max) {
        $node = array();
        foreach ($seed as $key) {
            $node[$key] = fillArray($depth + 1, $max);
        }
        return $node;
    }
    return 'empty';
}