PHP配列の保存に推奨される方法(json_encodeとシリアライズ)


608

キャッシュのために、データの多次元の連想配列をフラットファイルに保存する必要があります。Webアプリで使用するためにJSONに変換する必要がある場合がありますが、ほとんどの場合、配列をPHPで直接使用します。

配列をこのテキストファイルにJSONまたはPHPシリアル化配列として保存する方が効率的ですか?私は見回しましたが、PHPの最新バージョン(5.3)では、json_decode実際にはよりも高速であるようunserializeです。

私は現在、配列をJSONとして保存することに傾倒しています。必要に応じて人間が読みやすく、PHPとJavaScriptの両方でほとんど手間をかけずに使用できます。私が読んだことから、デコードが高速です(ただし、エンコードについては不明です)。

誰かが落とし穴を知っていますか?どちらかの方法のパフォーマンス上の利点を示す良いベンチマークを持っている人はいますか?

回答:


563

あなたの優先順位に依存します。

パフォーマンスが絶対的な運転特性である場合は、必ず最速のものを使用してください。選択する前に、違いを完全に理解していることを確認してください

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

そして、現時点では考えられない他のいくつかの違いがあるでしょう。

2つを比較する簡単な速度テスト

<?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';
}

31
「JSONはUTF-8文字をUnicodeエスケープシーケンスに変換します。」必ずしも本当ではありませんJSON_UNESCAPED_UNICODE
TRiG

32
ここでは、ほぼ5年後のことですが、もう一度テストを実行し(だけjson_encode)、現在のシリアル化より平均で約131%高速です。そのため、5.3.xではなく5.4.xでその機能にかなり優れた改善がいくつかあるはずです。具体的には、CentOS 6で5.4.24を実行しています。
KyleFarris 14年

8
私の場合には、我々は一度エンコードし、多くのことをデコードし、我々はアンシリアライズ対json_decodeをベンチマークし、結果はJSONは0.093269109725952秒<BR> json_decodeにアンシリアライズ0.06662392616272秒<BR> PHPでdcodedたので()おおよそ39.99パーセントはアンシリアライズよりも速かったです()
AMB 2014

21
興味深い:あなたは上でこのコードを実行した場合3v4l.org、最新のPHP7の開発が速くjson_encodeより実行シリアル化を構築します:「シリアル化())(76.53パーセント速くjson_encodeよりおよそだった」
marcvangend

21
2017年、PHP 7.1およびserialize() was roughly 35.04% faster than json_encode()
エリアスソアレス

239

JSONはPHPのシリアライゼーションフォーマットよりもシンプルで高速なので、以下の場合を除いて使用する必要があります。

  • 深くネストされた配列を格納しています:: json_decode()「JSONエンコードされたデータが127要素よりも深い場合、この関数はfalseを返します。」
  • 正しいクラスとしてシリアル化解除する必要があるオブジェクトを保存している
  • json_decodeをサポートしていない古いバージョンのPHPとやり取りしている

12
すばらしい答えです。ハハ、127レベルの深さは少し気が狂っているようです。ありがたいことに、私はせいぜい2-3のようにしか行きません。json_decode / json_encodeがunserialize / serializeより速いという事実を裏付けるデータはありますか?
KyleFarris 2009

1
私はそれを少し前にテストしました、そして、jsonはより速く出ました-私はもうデータを持っていません。
グレッグ

47
「5.3.0オプションの深度が追加されました。デフォルトの再帰深度が128から512に増加しました」
giorgio79

4
上記のリストにもう1つ項目を追加します。データに無効なUTF-8バイトシーケンスが含まれている可能性がある場合は、json_encode()を使用しないでください。そのようなデータに対しては単にfalseを返します。たとえば、次を試してください:var_dump(json_encode( "\ xEF \ xEF"));
pako

2
一般的に高速であるとは言えません。約500エントリの小さな配列がある場合、unserialize / serializeは実際にはjson_decode / json_encode(PHP 5.6.19)よりも200〜400%高速です
Adam

59

私は、このテーマに関するブログ記事書いた:キャッシュの大きな配列:?JSONシリアライズまたはでvar_exportを。この投稿では、小規模から大規模の配列に対して直列化が最良の選択であることを示しています。非常に大きな配列(> 70MB)の場合は、JSONの方が適しています。


8
リンクはもう利用できません。
マーティントーマ2015

1
おかげで、ムース、私はリンクを更新しました。記事はほぼ6年前のものであり、現在のPHPバージョンではそれほど正確ではない可能性があります。
Taco

私はいくつかのテストを行い、それをテストするための単純な関数を作成しました。大きな配列(Peter Baileyの関数を使用)を使用すると、約300回の反復で、よりもjson_encode()80%から150%高速です(実際に上下に移動します)serialize()。しかし、より小さな配列(array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players))))を使用する場合、750,000回の反復でテストを行いましたserialize()が、その場合は約6%〜10%高速です。私の関数はすべての反復の平均時間を取り、それらを比較します。私はそれを答えの1つとしてここに投稿するかもしれません
MiChAeLoKGB

データがPHPでのみ使用される場合、var_exportが私の物です。インクルードの考えで起こり得る構文エラーに注意する必要があるだけです。
Gfra54

3
ブログはもう存在しません
popeye

53

また、https://github.com/phadej/igbinaryにも興味があるかもしれませんこれは、PHPに異なるシリアル化「エンジン」を提供します。

64ビットプラットフォームでPHP 5.3.5を使用した私のランダム/任意の「パフォーマンス」の数値

JSON:

  • 2.180496931076秒でエンコードされたJSON
  • JSONは9.8368630409241秒でデコードされます
  • シリアル化された「文字列」サイズ:13993

ネイティブPHP:

  • PHPは2.9125759601593秒でシリアル化されました
  • PHPは6.4348418712616秒でシリアル化解除されます
  • シリアル化された「文字列」サイズ:20769

Igbinary:

  • WIN igbinaryは1.6099879741669秒でシリアル化されました
  • 4.7737920284271秒でシリアル化されていないigbinraryをWIN
  • WINシリアル化された "String"サイズ:4467

そのため、igbinary_serialize()とigbinary_unserialize()の方が速く、使用するディスク容量も少なくなります。

上記のようにfillArray(0、3)コードを使用しましたが、配列キーをより長い文字列にしました。

igbinaryは、PHPのネイティブシリアライズと同じデータ型を格納できるため(オブジェクトなどに問題はありません)、必要に応じて、PHP5.3でセッション処理に使用するように指示できます。

http://ilia.ws/files/zendcon_2010_hidden_​​features.pdfも参照-特にスライド14/15/16


25

Yは、シリアル化され、jsonエンコードとデコードをテストしたばかりでなく、格納されている文字列を取得するサイズもテストしました。

JSON encoded in 0.067085981369 seconds. Size (1277772)
PHP serialized in 0.12110209465 seconds. Size (1955548)
JSON decode in 0.22470498085 seconds
PHP serialized in 0.211947917938 seconds
json_encode() was roughly 80.52% faster than serialize()
unserialize() was roughly 6.02% faster than json_decode()
JSON string was roughly 53.04% smaller than Serialized string

JSONはより高速にエンコードし、結果として文字列が小さくなると結論付けることができますが、unserializeは文字列をデコードするのに高速です。


6
なぜ人々がいつもこんなに小さいデータセットでパフォーマンステストをするのか、私にはわかりません。そうすることで、結果にエラーを追加するすべてのオーバーヘッドが発生します。そして、人々がパフォーマンスに興味を持っているなら、それはおそらく彼らが非常に大きなデータセットを持っているためでしょう、なぜならマイクロ秒を一度獲得する意味がないからです。
Yann Sagon、2012年

1
多くの場合、多くの小さなデータセットを繰り返し処理します。数百の小さなデータセットがあり、それぞれに1mSを獲得することは依然として興味深いです。
Teson 2014

@YannSagon小さなデータセットでも、パフォーマンステストを行うのは理にかなっています。テストが1マイクロ秒程度であるかどうかをテスト前にどのように知る必要がありますか?
アダム

17

後で最終的に「含める」情報をキャッシュする場合は、var_exportを使用してみてください。この方法では、「シリアライズ」でのみヒットを取得し、「アンシリアライズ」ではヒットを取得しません。


これがおそらく最も速い方法です。-私はSO「PHPに例を書いた速い:シリアル化/アンシリアライズ」stackoverflow.com/questions/2545455/...
dave1010

12

シリアル化解除のパフォーマンスを含めるようにテストを拡張しました。ここに私が得た数があります。

Serialize

JSON encoded in 2.5738489627838 seconds
PHP serialized in 5.2861361503601 seconds
Serialize: json_encode() was roughly 105.38% faster than serialize()


Unserialize

JSON decode in 10.915472984314 seconds
PHP unserialized in 7.6223039627075 seconds
Unserialize: unserialize() was roughly 43.20% faster than json_decode() 

したがって、jsonはエンコードは高速ですが、デコードは低速のようです。したがって、それはアプリケーションと、最も期待することによって異なります。


9

本当にいいトピックで、いくつかの回答を読んだ後、このテーマに関する私の実験を共有したいと思います。

ほとんどの場合、データベースにアクセスするたびに「巨大な」テーブルにクエリを実行する必要があるというユースケースがありました(理由は尋ねないでください。データベースキャッシングシステムは、さまざまなリクエストをキャッシュしないので適切ではありません。

私は試した apcuが、ニーズに合いませんでした。この場合、メモリは十分に信頼できません。次のステップは、シリアライゼーションを使用してファイルにキャッシュすることでした。

テーブルには18列の14355エントリがあります。これらは、シリアル化されたキャッシュの読み取りに関する私のテストと統計です。

JSON:

あなたがすべて言ったように、主な不便 json_encode /json_decodeは、すべてをStdClassインスタンス(またはオブジェクト)に変換することです。ループする必要がある場合、配列に変換することはおそらく行うことであり、はい、変換時間を増やしています

平均時間:780.2ミリ秒。メモリ使用量:41.5MB; キャッシュファイルサイズ:3.8MB

メッセージパック

@hutchはmsgpackについて言及しています。かなりのウェブサイト。やってみましょうか。

平均時間:497ミリ秒。メモリ使用量:32MB; キャッシュファイルサイズ:2.8MB

それはより良いですが、新しい拡張が必要です。時々怖い人をコンパイルしています...

IgBinary

@GingerDogはigbinaryについて言及していますigbinary.compact_strings=Offファイルサイズよりも読み取りパフォーマンスを重視するため、設定したことに注意してください。

平均時間:411.4 ms; メモリ使用量:36.75MB; キャッシュファイルサイズ:3.3MB

メッセージパックよりも優れています。それでも、これもコンパイルが必要です。

serialize/unserialize

平均時間:477.2 ms; メモリ使用量:36.25MB; キャッシュファイルサイズ:5.9MB

JSONよりもパフォーマンスが良いほど、配列は大きくなりますjson_decodeが、速度は遅くなりますが、すでに新しいものです。

これらの外部拡張子はファイルサイズを狭くしており、紙の上では素晴らしいようです。数字は嘘をつかない*。標準のPHP関数とほぼ同じ結果が得られる場合、拡張機能をコンパイルする意味は何ですか?

また、ニーズに応じて、他の人とは異なるものを選択することもできます。

  • IgBinaryは本当に素晴らしく、MsgPackよりもパフォーマンスが優れています
  • Msgpackは、データの圧縮に優れています(igbinaryのcompact.stringオプションは試していません)。
  • コンパイルしたくないですか?標準を使用します。

それだけです。別のものを選択するのに役立つ別のシリアル化メソッドの比較です。

* PHPUnit 3.7.31、php 5.5.10でテスト-標準のハードドライブと古いデュアルコアCPUでのみデコード-10件の同じユースケーステストの平均数、統計は異なる場合があります


json_decodeにフラグを渡して配列を強制的に返さないのはなぜですか?
Alex Yaroshevich 2014年

遅いから。私はこれをテストしませんでしたが、単純にphpからの型変更を強制する方が速いと思います。
soyuka 2014年

私はPHPでオブジェクトよりもはるかに速く配列を作成することを知っています。
Alex Yaroshevich 2014年

つまりjson_decode($object, true)、について話していますが、基本的にはと同じです(array) json_decode($object)が再帰的に実行されるため、同じ動作になり、どちらの場合もかなりのコストがかかります。StdClassとの間のパフォーマンスの違いをテストしていないことに注意してarrayください。
soyuka 2014年

オブジェクトなしで下位レベルで行われるため、別のコストになると思います。
Alex Yaroshevich 2014年

8

シリアライズのように見えるのは、2つの理由で使用するものです。

  • unserializeはjson_decodeよりも高速であり、「読み取り」の場合は「書き込み」の場合よりも可能性が高いと誰かが指摘しました。

  • 無効なUTF-8文字の文字列がある場合、json_encodeで問題が発生しました。その場合、文字列は空になり、情報が失われます。


最後のポイントについて例を挙げて詳しく説明してもらえますか
Naveen Saroye

6

私はすべての種類のデータ(文字列、NULL、整数)が含まれるかなり複雑で穏やかにネストされたマルチハッシュでこれを非常に徹底的にテストしました。

私のテストにおけるjsonの唯一の利点は、それがより小さな「パック」サイズであるということです。

これらはPHP 5.3.3で行われます。詳細が必要な場合はお知らせください。

テスト結果とそれを生成するコードを次に示します。テストデータを提供することはできません。実際に公開できない情報が明らかになるためです。

JSON encoded in 2.23700618744 seconds
PHP serialized in 1.3434419632 seconds
JSON decoded in 4.0405561924 seconds
PHP unserialized in 1.39393305779 seconds

serialized size : 14549
json_encode size : 11520
serialize() was roughly 66.51% faster than json_encode()
unserialize() was roughly 189.87% faster than json_decode()
json_encode() string was roughly 26.29% smaller than serialize()

//  Time json encoding
$start = microtime( true );
for($i = 0; $i < 10000; $i++) {
    json_encode( $test );
}
$jsonTime = microtime( true ) - $start;
echo "JSON encoded in $jsonTime seconds<br>";

//  Time serialization
$start = microtime( true );
for($i = 0; $i < 10000; $i++) {
    serialize( $test );
}
$serializeTime = microtime( true ) - $start;
echo "PHP serialized in $serializeTime seconds<br>";

//  Time json decoding
$test2 = json_encode( $test );
$start = microtime( true );
for($i = 0; $i < 10000; $i++) {
    json_decode( $test2 );
}
$jsonDecodeTime = microtime( true ) - $start;
echo "JSON decoded in $jsonDecodeTime seconds<br>";

//  Time deserialization
$test2 = serialize( $test );
$start = microtime( true );
for($i = 0; $i < 10000; $i++) {
    unserialize( $test2 );
}
$unserializeTime = microtime( true ) - $start;
echo "PHP unserialized in $unserializeTime seconds<br>";

$jsonSize = strlen(json_encode( $test ));
$phpSize = strlen(serialize( $test ));

echo "<p>serialized size : " . strlen(serialize( $test )) . "<br>";
echo "json_encode size : " . strlen(json_encode( $test )) . "<br></p>";

//  Compare them
if ( $jsonTime < $serializeTime )
{
    echo "json_encode() was roughly " . number_format( ($serializeTime / $jsonTime - 1 ) * 100, 2 ) . "% faster than serialize()";
}
else if ( $serializeTime < $jsonTime )
{
    echo "serialize() was roughly " . number_format( ($jsonTime / $serializeTime - 1 ) * 100, 2 ) . "% faster than json_encode()";
} else {
    echo 'Unpossible!';
}
    echo '<BR>';

//  Compare them
if ( $jsonDecodeTime < $unserializeTime )
{
    echo "json_decode() was roughly " . number_format( ($unserializeTime / $jsonDecodeTime - 1 ) * 100, 2 ) . "% faster than unserialize()";
}
else if ( $unserializeTime < $jsonDecodeTime )
{
    echo "unserialize() was roughly " . number_format( ($jsonDecodeTime / $unserializeTime - 1 ) * 100, 2 ) . "% faster than json_decode()";
} else {
    echo 'Unpossible!';
}
    echo '<BR>';
//  Compare them
if ( $jsonSize < $phpSize )
{
    echo "json_encode() string was roughly " . number_format( ($phpSize / $jsonSize - 1 ) * 100, 2 ) . "% smaller than serialize()";
}
else if ( $phpSize < $jsonSize )
{
    echo "serialize() string was roughly " . number_format( ($jsonSize / $phpSize - 1 ) * 100, 2 ) . "% smaller than json_encode()";
} else {
    echo 'Unpossible!';
}

PHP 5.4.12で同様のテストを実行したところ、同様の結果が見つかりました。{un、} serializeの方が高速です。私のデータは、ネストされた3レベルの深さのハッシュです(900kシリアル化)。
13

6

小さなベンチマークも作成しました。私の結果は同じでした。しかし、デコードのパフォーマンスが必要です。私が気づいたのは、上記の数人の人もそうであるように、unserializeよりも速いことjson_decodeです。unserialize時間の約60〜70%がかかりますjson_decode。したがって、結論は非常に単純です。エンコードでjson_encodeパフォーマンスが必要な場合はを使用し、デコードでパフォーマンスが必要な場合はunserialize。2つの機能をマージすることはできないため、より高いパフォーマンスが必要な場所を選択する必要があります。

疑似の私のベンチマーク:

  • いくつかのランダムなキーと値で配列$ arrを定義します
  • x <100の場合; x ++; $ arrのarray_randをシリアライズしてjson_encode
  • y <1000の場合; y ++; json_decode jsonエンコードされた文字列-計算時間
  • y <1000の場合; y ++; シリアル化された文字列のシリアル化解除-計算時間
  • より速い結果をエコーし​​ます

avarageの場合:unserializeがjson_decodeの4倍を超える96回勝ちました。2.5msより約1.5msの平均を使用します。


3

最終的な決定を行う前に、JSON形式は連想配列に対して安全ではないことに注意してください- json_decode()代わりにそれらをオブジェクトとして返します:

$config = array(
    'Frodo'   => 'hobbit',
    'Gimli'   => 'dwarf',
    'Gandalf' => 'wizard',
    );
print_r($config);
print_r(json_decode(json_encode($config)));

出力は次のとおりです。

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)

確かに、あなたは正しいです。私はそれが、意味ある Javascriptのオブジェクトやっぱ記法!ありがたいことに、使用してエンコードしたものが連想配列であることがわかっている場合json_encodeは、次のように簡単に強制的に配列に戻すことができます。$json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);また、PHPの配列と同じ方法でオブジェクトにアクセスできるため、一般的なシナリオでは、違いさえわからないでしょう。良い点も!
KyleFarris 2009

30
@toomuchphp、申し訳ありませんが、あなたは間違っています。json_decodeに配列を生成させるjson_decode 'bool $ assoc = false'の2番目のパラメーターがあります。@KyleFarris。これは、配列への型キャストを使用するよりも高速です。
janpio 2010年

答えは正しくありません。関数の2番目のパラメーターとしてtrueを使用すると、json_decode()はオブジェクトではなく連想配列を返します。
Marvin Saldinger、2015

3

まず、スクリプトを変更してさらにベンチマークを実行します(1つだけでなく1000回実行します)。

<?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);

$totalJsonTime = 0;
$totalSerializeTime = 0;
$totalJsonWins = 0;

for ($i = 0; $i < 1000; $i++) {
    // Time json encoding
    $start = microtime(true);
    $json = json_encode($testArray);
    $jsonTime = microtime(true) - $start;
    $totalJsonTime += $jsonTime;

    // Time serialization
    $start = microtime(true);
    $serial = serialize($testArray);
    $serializeTime = microtime(true) - $start;
    $totalSerializeTime += $serializeTime;

    if ($jsonTime < $serializeTime) {
        $totalJsonWins++;
    }
}

$totalSerializeWins = 1000 - $totalJsonWins;

// Compare them
if ($totalJsonTime < $totalSerializeTime) {
    printf("json_encode() (wins: $totalJsonWins) was roughly %01.2f%% faster than serialize()\n", ($totalSerializeTime / $totalJsonTime - 1) * 100);
} else {
    printf("serialize() (wins: $totalSerializeWins) was roughly %01.2f%% faster than json_encode()\n", ($totalJsonTime / $totalSerializeTime - 1) * 100);
}

$totalJsonTime = 0;
$totalJson2Time = 0;
$totalSerializeTime = 0;
$totalJsonWins = 0;

for ($i = 0; $i < 1000; $i++) {
    // Time json decoding
    $start = microtime(true);
    $orig = json_decode($json, true);
    $jsonTime = microtime(true) - $start;
    $totalJsonTime += $jsonTime;

    $start = microtime(true);
    $origObj = json_decode($json);
    $jsonTime2 = microtime(true) - $start;
    $totalJson2Time += $jsonTime2;

    // Time serialization
    $start = microtime(true);
    $unserial = unserialize($serial);
    $serializeTime = microtime(true) - $start;
    $totalSerializeTime += $serializeTime;

    if ($jsonTime < $serializeTime) {
        $totalJsonWins++;
    }
}

$totalSerializeWins = 1000 - $totalJsonWins;


// Compare them
if ($totalJsonTime < $totalSerializeTime) {
    printf("json_decode() was roughly %01.2f%% faster than unserialize()\n", ($totalSerializeTime / $totalJsonTime - 1) * 100);
} else {
    printf("unserialize() (wins: $totalSerializeWins) was roughly %01.2f%% faster than json_decode()\n", ($totalJsonTime / $totalSerializeTime - 1) * 100);
}

// Compare them
if ($totalJson2Time < $totalSerializeTime) {
    printf("json_decode() was roughly %01.2f%% faster than unserialize()\n", ($totalSerializeTime / $totalJson2Time - 1) * 100);
} else {
    printf("unserialize() (wins: $totalSerializeWins) was roughly %01.2f%% faster than array json_decode()\n", ($totalJson2Time / $totalSerializeTime - 1) * 100);
}

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';
}

私はこのビルドのPHP 7を使用しました:

PHP 7.0.14(cli)(ビルド:Jan 18 2017 19:13:23)(NTS)Copyright(c)1997-2016 PHP Group Zend Engine v3.0.0、Copyright(c)1998-2016 Zend Technologies with Zend OPcache v7.0.14、著作権(c)1999-2016、Zend Technologies製

そして私の結果は:

serialize()(wins:999)はjson_encode()より約10.98%高速でしたunserialize()(wins:987)はjson_decode()より約33.26%高速でしたunserialize()(wins:987)は配列json_decodeより約48.35%高速でした()

したがって、明らかに、serialize / unserializeが最も高速なメソッドであり、json_encode / decodeが最も移植性があります。

シリアライズされたデータを非PHPシステムとの間で送受信する必要がある頻度よりも10倍以上読み書きするシナリオを検討する場合は、シリアライズ/アンシリアライズを使用して、シリアライズの前にjson_encodeまたはjson_decodeを使用するほうがよいでしょう。時間の面で。


2

ここで結果を確認してください(JSコードボックスにPHPコードを配置するハックは申し訳ありません)。

http://jsfiddle.net/newms87/h3b0a0ha/embedded/result/

結果:serialize()およびunserialize()、PHP 5.4では、サイズが異なる配列でも、どちらも大幅に高速化されています。

json_encodeとserialize、json_decodeとunserializeを比較するために、実際のデータでテストスクリプトを作成しました。テストは、運用中のeコマースサイトのキャッシュシステムで実行されました。それは単にキャッシュに既にあるデータを取り、すべてのデータをエンコード/デコード(またはシリアライズ/アンシリアライズ)する時間をテストし、見やすいテーブルに入れます。

これをPHP 5.4共有ホスティングサーバーで実行しました。

結果は非常に決定的で、これらの大規模なデータセットから小規模なデータセットに対して、シリアル化とシリアル化解除が明らかに勝者でした。特に私の使用例では、json_decodeとunserializeがキャッシュシステムにとって最も重要です。Unserializeは、ユビキタスな勝者でした。通常、json_decodeの2〜4倍(場合によっては6または7倍)の速度でした。

@ peter-baileyの結果の違いに注目するのは興味深いことです。

以下は、結果を生成するために使用されるPHPコードです。

<?php

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

function _count_depth($array)
{
    $count     = 0;
    $max_depth = 0;
    foreach ($array as $a) {
        if (is_array($a)) {
            list($cnt, $depth) = _count_depth($a);
            $count += $cnt;
            $max_depth = max($max_depth, $depth);
        } else {
            $count++;
        }
    }

    return array(
        $count,
        $max_depth + 1,
    );
}

function run_test($file)
{
    $memory     = memory_get_usage();
    $test_array = unserialize(file_get_contents($file));
    $memory     = round((memory_get_usage() - $memory) / 1024, 2);

    if (empty($test_array) || !is_array($test_array)) {
        return;
    }

    list($count, $depth) = _count_depth($test_array);

    //JSON encode test
    $start            = microtime(true);
    $json_encoded     = json_encode($test_array);
    $json_encode_time = microtime(true) - $start;

    //JSON decode test
    $start = microtime(true);
    json_decode($json_encoded);
    $json_decode_time = microtime(true) - $start;

    //serialize test
    $start          = microtime(true);
    $serialized     = serialize($test_array);
    $serialize_time = microtime(true) - $start;

    //unserialize test
    $start = microtime(true);
    unserialize($serialized);
    $unserialize_time = microtime(true) - $start;

    return array(
        'Name'                   => basename($file),
        'json_encode() Time (s)' => $json_encode_time,
        'json_decode() Time (s)' => $json_decode_time,
        'serialize() Time (s)'   => $serialize_time,
        'unserialize() Time (s)' => $unserialize_time,
        'Elements'               => $count,
        'Memory (KB)'            => $memory,
        'Max Depth'              => $depth,
        'json_encode() Win'      => ($json_encode_time > 0 && $json_encode_time < $serialize_time) ? number_format(($serialize_time / $json_encode_time - 1) * 100, 2) : '',
        'serialize() Win'        => ($serialize_time > 0 && $serialize_time < $json_encode_time) ? number_format(($json_encode_time / $serialize_time - 1) * 100, 2) : '',
        'json_decode() Win'      => ($json_decode_time > 0 && $json_decode_time < $serialize_time) ? number_format(($serialize_time / $json_decode_time - 1) * 100, 2) : '',
        'unserialize() Win'      => ($unserialize_time > 0 && $unserialize_time < $json_decode_time) ? number_format(($json_decode_time / $unserialize_time - 1) * 100, 2) : '',
    );
}

$files = glob(dirname(__FILE__) . '/system/cache/*');

$data = array();

foreach ($files as $file) {
    if (is_file($file)) {
        $result = run_test($file);

        if ($result) {
            $data[] = $result;
        }
    }
}

uasort($data, function ($a, $b) {
    return $a['Memory (KB)'] < $b['Memory (KB)'];
});

$fields = array_keys($data[0]);
?>

<table>
    <thead>
    <tr>
        <?php foreach ($fields as $f) { ?>
            <td style="text-align: center; border:1px solid black;padding: 4px 8px;font-weight:bold;font-size:1.1em"><?= $f; ?></td>
        <?php } ?>
    </tr>
    </thead>

    <tbody>
    <?php foreach ($data as $d) { ?>
        <tr>
            <?php foreach ($d as $key => $value) { ?>
                <?php $is_win = strpos($key, 'Win'); ?>
                <?php $color = ($is_win && $value) ? 'color: green;font-weight:bold;' : ''; ?>
                <td style="text-align: center; vertical-align: middle; padding: 3px 6px; border: 1px solid gray; <?= $color; ?>"><?= $value . (($is_win && $value) ? '%' : ''); ?></td>
            <?php } ?>
        </tr>
    <?php } ?>
    </tbody>
</table>

1

単なるfyi-データをJSONのように読みやすく理解しやすいものにシリアル化したいが、圧縮率が高く、パフォーマンスが高い場合は、メッセージパックをチェックしてください


2
単なるfyiの場合は、コメントとして記述してください。
technophyle

0

JSONは、データをバックアップして別のマシンまたはFTP経由で復元する場合に適しています。

たとえば、serializeを使用してデータをWindowsサーバーに保存し、FTP経由でダウンロードしてLinuxに復元した場合、charachterの再エンコードのために機能しなくなります。serializeは文字列の長さとUnicodeを保存するためです。 > UTF-8トランスコーディングで1バイト文字が2バイト長になり、アルゴリズムがクラッシュすることがありました。


0

THX-このベンチマークコードの場合:

構成に使用する配列の結果はダメです:0.0031511783599854秒でエンコードされたJSON 0.0037961006164551秒でシリアル化された
PHPは、0.0070841312408447秒
json_encode()serialize() エンコードされたJSON よりも約
20.47
unserialize()%高速でした。json_encode()

だから-あなた自身のデータでそれをテストしてください。


「unserialize()のjson_decode()はjson_encode()よりもおよそ97.66%高速だった」という意味ですか?
Meezaan-ud-Din 2014

0

ここで人々が言うことを要約すると、json_decode / encodeはシリアライズ/アンシリアライズよりも高速に見えますが、var_dumpを実行すると、シリアライズされたオブジェクトのタイプが変更されます。なんらかの理由でタイプを保持したい場合は、シリアライズしてください!

(たとえば、stdClass vs配列を試してください)

シリアライズ/アンシリアライズ:

Array cache:
array (size=2)
  'a' => string '1' (length=1)
  'b' => int 2
Object cache:
object(stdClass)[8]
  public 'field1' => int 123
This cache:
object(Controller\Test)[8]
  protected 'view' => 

jsonエンコード/デコード

Array cache:
object(stdClass)[7]
  public 'a' => string '1' (length=1)
  public 'b' => int 2
Object cache:
object(stdClass)[8]
  public 'field1' => int 123
This cache:
object(stdClass)[8]

ご覧のように、json_encode / decodeはすべてをstdClassに変換しますが、これは良いことではなく、オブジェクト情報が失われます...したがって、特に配列だけではない場合は、ニーズに基づいて決定してください...


注:他のほとんどの回答では、シリアライズ/アンシリアライズの方が高速であるとしています。
Ecker00

-3

Super Cacheを使用することをお勧めします。これは、json_encodeまたはを使用しないファイルキャッシュメカニズムserializeです。他のPHPキャッシュメカニズムと比較すると、使い方は簡単で、本当に高速です。

https://packagist.org/packages/smart-php/super-cache

例:

<?php
require __DIR__.'/vendor/autoload.php';
use SuperCache\SuperCache as sCache;

//Saving cache value with a key
// sCache::cache('<key>')->set('<value>');
sCache::cache('myKey')->set('Key_value');

//Retrieving cache value with a key
echo sCache::cache('myKey')->get();
?>

-1。それはより良い解決策かもしれませんが、この回答のどの部分も実際にOPの質問に答えることはありません。将来的には、おそらく質問に答えてみてくださいが、代替ソリューションが調査に値するかもしれないという提案を下部に残してください。
starbeamrainbowlabs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.