Metode yang disukai untuk menyimpan array PHP (json_encode vs serialize)

608

Saya perlu menyimpan array asosiatif multi-dimensi data dalam file datar untuk tujuan caching. Saya terkadang menemukan kebutuhan untuk mengubahnya ke JSON untuk digunakan di aplikasi web saya, tetapi sebagian besar waktu saya akan menggunakan array secara langsung di PHP.

Apakah akan lebih efisien untuk menyimpan array sebagai JSON atau sebagai array serial PHP dalam file teks ini? Saya sudah melihat-lihat dan sepertinya dalam versi terbaru PHP (5.3), json_decodesebenarnya lebih cepat daripada unserialize.

Saat ini saya condong ke arah penyimpanan array sebagai JSON karena saya merasa lebih mudah dibaca oleh manusia jika perlu, dapat digunakan dalam PHP dan JavaScript dengan sedikit usaha, dan dari apa yang saya baca, mungkin bahkan lebih cepat untuk memecahkan kode (meskipun tidak yakin tentang penyandian).

Apakah ada yang tahu tentang jebakan? Adakah yang memiliki tolok ukur yang baik untuk menunjukkan manfaat kinerja dari kedua metode tersebut?

KyleFarris
sumber

Jawaban:

563

Tergantung pada prioritas Anda.

Jika kinerja adalah karakteristik mengemudi mutlak Anda, maka tentu saja gunakan yang tercepat. Pastikan Anda memiliki pemahaman penuh tentang perbedaan sebelum Anda membuat pilihan

  • Tidak seperti serialize()Anda perlu menambahkan parameter tambahan untuk menjaga agar karakter UTF-8 tidak tersentuh: json_encode($array, JSON_UNESCAPED_UNICODE) (jika tidak, ia mengubah karakter UTF-8 ke urutan pelepasan Unicode).
  • JSON tidak akan memiliki memori tentang apa kelas asli objek itu (mereka selalu dikembalikan sebagai instance dari stdClass).
  • Anda tidak dapat memanfaatkan __sleep()dan __wakeup()dengan JSON
  • Secara default, hanya properti publik yang diserialisasi dengan JSON. ( PHP>=5.4Anda dapat mengimplementasikan JsonSerializable untuk mengubah perilaku ini).
  • JSON lebih portabel

Dan mungkin ada beberapa perbedaan lain yang tidak dapat saya pikirkan saat ini.

Tes kecepatan sederhana untuk membandingkan keduanya

<?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';
}
Peter Bailey
sumber
31
"JSON mengubah karakter UTF-8 menjadi unicode sequence escape." Tidak lagi benar: kita sekarang punya JSON_UNESCAPED_UNICODE.
TRiG
32
Di sini kita hampir 5 tahun kemudian dan saya menjalankan tes lagi (hanya json_encode) dan itu rata-rata sekitar 131% lebih cepat daripada cerita bersambung sekarang. Jadi, harus ada beberapa perbaikan yang cukup bagus untuk fungsi itu di 5.4.x lebih dari 5.3.x. Secara khusus, saya menjalankan 5.4.24 pada CentOS 6. Jadi, yay untuk JSON !!
KyleFarris
8
dalam kasus saya, kami menyandikan sekali dan men-decode banyak, jadi kami membuat tolok ukur json_decode vs unserialize dan hasilnya JSON dikodekan dalam 0,06662392616272 detik <br> PHP unserialized dalam 0,093269109725952 detik <br> json_decode () kira-kira 39,99% lebih cepat daripada unserialize ()
AMB
21
Menarik: jika Anda menjalankan kode ini di 3v4l.org , pengembangan PHP7 terbaru menjalankan serialisasi lebih cepat daripada json_encode: "serialize () kira-kira 76,53% lebih cepat daripada json_encode ()"
marcvangend
21
2017, PHP 7.1 danserialize() was roughly 35.04% faster than json_encode()
Elias Soares
239

JSON lebih sederhana dan lebih cepat daripada format serialisasi PHP dan harus digunakan kecuali :

  • Anda menyimpan array yang sangat bersarang json_decode():: "Fungsi ini akan mengembalikan false jika data yang dikodekan JSON lebih dalam dari 127 elemen."
  • Anda menyimpan objek yang perlu di-unserialized sebagai kelas yang benar
  • Anda berinteraksi dengan versi PHP lama yang tidak mendukung json_decode
Greg
sumber
12
Jawaban yang bagus Haha, kedalaman 127 level sepertinya agak gila; untungnya saya hanya akan seperti 2-3 paling banyak. Apakah Anda memiliki data untuk mendukung fakta bahwa json_decode / json_encode lebih cepat daripada unserialize / serialize?
KyleFarris
1
Saya mengujinya beberapa saat yang lalu dan json keluar lebih cepat - saya tidak punya data lagi.
Greg
47
"5.3.0 Menambahkan kedalaman opsional. Kedalaman rekursi default ditingkatkan dari 128 menjadi 512"
giorgio79
4
Saya akan menambahkan satu item lagi ke daftar di atas: json_encode () tidak boleh digunakan jika data Anda mungkin mengandung urutan byte UTF-8 byte yang tidak valid. Ini hanya mengembalikan false untuk data tersebut. Coba misalnya: var_dump (json_encode ("\ xEF \ xEF"));
pako
2
Tidak benar bahwa secara umum lebih cepat. Jika Anda memiliki array kecil dengan sekitar ~ 500 entri, maka unserialize / serialisasi sebenarnya 200-400% lebih cepat daripada json_decode / json_encode (PHP 5.6.19)
Adam
59

Saya telah menulis posting blog tentang subjek ini: " Cache a array besar: JSON, serialize atau var_export? " . Dalam posting ini ditunjukkan bahwa serialisasi adalah pilihan terbaik untuk array berukuran kecil hingga besar. Untuk array yang sangat besar (> 70MB) JSON adalah pilihan yang lebih baik.

Taco
sumber
8
Tautan tidak tersedia lagi.
Martin Thoma
1
Terima kasih, moose, saya telah memperbarui tautannya. Meskipun artikel ini hampir berumur 6 tahun dan mungkin tidak terlalu akurat untuk versi PHP saat ini.
Taco
Saya melakukan beberapa tes dan membuat fungsi sederhana untuk mengujinya, dengan array besar (fungsi yang digunakan Peter Bailey untuk itu) json_encode()adalah sekitar 80% hingga 150% lebih cepat (itu benar-benar naik dan turun di sana) daripada serialize(), dengan sekitar 300 iterasi. Tetapi ketika menggunakan array yang lebih kecil ( array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))), saya melakukan tes dengan 750.000 iterasi dan serialize()sekitar 6% hingga 10% lebih cepat dalam kasus itu. Fungsi saya mengambil waktu rata-rata untuk semua iterasi dan membandingkannya. Saya mungkin mempostingnya di sini sebagai salah satu jawaban
MiChAeLoKGB
jika data hanya digunakan oleh PHP, var_export adalah hal saya. Hanya perlu berhati-hati dengan kemungkinan kesalahan sintaksis dalam pemikiran termasuk.
Gfra54
3
blog tidak ada lagi
popeye
53

Anda mungkin juga tertarik dengan https://github.com/phadej/igbinary - yang menyediakan 'mesin' serialisasi yang berbeda untuk PHP.

Angka 'kinerja' saya yang acak / arbitrer, menggunakan PHP 5.3.5 pada platform 64bit:

JSON:

  • JSON disandikan dalam 2,180496931076 detik
  • JSON diterjemahkan dalam 9,8368630409241 detik
  • serial "String" ukuran: 13993

PHP asli:

  • PHP diserialisasi dalam 2,9125759601593 detik
  • PHP tidak terdaftar dalam 6,4348418712616 detik
  • serial "String" ukuran: 20769

Igbinary:

  • MENANG igbinary diserialisasi dalam 1,6099879741669 detik
  • MENANGKAN igbinrary unserialized dalam 4,7737920284271 detik
  • MENANGKAN serial "String" Ukuran: 4467

Jadi, lebih cepat untuk igbinary_serialize () dan igbinary_unserialize () dan menggunakan lebih sedikit ruang disk.

Saya menggunakan kode fillArray (0, 3) seperti di atas, tetapi membuat string array lebih panjang.

igbinary dapat menyimpan tipe data yang sama dengan serialize asli PHP (Jadi tidak ada masalah dengan objek, dll) dan Anda dapat memberitahu PHP5.3 untuk menggunakannya untuk penanganan sesi jika diinginkan.

Lihat juga http://ilia.ws/files/zendcon_2010_hidden_features.pdf - khusus slide 14/15/16

David Goodwin
sumber
25

Y baru saja menguji serial dan json mengenkode dan mendekode, ditambah ukurannya akan mengambil string yang disimpan.

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

Kita dapat menyimpulkan bahwa JSON mengkodekan lebih cepat dan menghasilkan string yang lebih kecil, tetapi membatalkan registrasi lebih cepat untuk men-decode string.

Gagal
sumber
6
Saya tidak tahu mengapa orang selalu melakukan tes kinerja dengan dataset yang sangat kecil. Melakukan itu Anda memiliki semua overhead yang menambah kesalahan pada hasil Anda. Dan jika orang tertarik pada kinerja itu mungkin karena mereka memiliki dataset yang sangat besar, karena tidak ada gunanya mendapatkan mikro detik sekali.
Yann Sagon
1
Cukup sering saya mengulangi banyak dataset kecil. Dengan ratusan set data kecil, mendapatkan 1ms untuk masing-masing masih menarik.
Teson
@YannSagon Bahkan dengan dataset kecil, masuk akal untuk melakukan tes kinerja. Bagaimana Anda tahu sebelum tes jika hanya sekitar satu mikro detik?
Adam
17

Jika Anda menyimpan informasi yang pada akhirnya ingin Anda "sertakan" pada saatnya nanti, Anda mungkin ingin mencoba menggunakan var_export . Dengan begitu Anda hanya menerima hit di "serialize" dan bukan di "unserialize".

Jordan S. Jones
sumber
Ini mungkin cara tercepat yang mungkin. Saya menulis sebuah contoh pada SO "PHP - fast serialize / unserialize": stackoverflow.com/questions/2545455/…
dave1010
12

Saya menambah tes untuk memasukkan kinerja unserialisasi. Ini nomor yang saya dapat.

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() 

Jadi json sepertinya lebih cepat untuk encoding tetapi lambat dalam decoding. Jadi itu bisa bergantung pada aplikasi Anda dan apa yang paling Anda harapkan.

Jeff Whiting
sumber
9

Topik yang sangat bagus dan setelah membaca beberapa jawaban, saya ingin membagikan eksperimen saya pada subjek.

Saya punya kasus penggunaan di mana beberapa tabel "besar" perlu ditanyakan hampir setiap kali saya berbicara dengan database (jangan tanya mengapa, hanya fakta). Sistem caching basis data tidak sesuai karena tidak akan men-cache permintaan yang berbeda, jadi saya berpikir tentang sistem caching php.

Saya mencoba apcutetapi tidak sesuai dengan kebutuhan, memori tidak cukup dapat diandalkan dalam hal ini. Langkah selanjutnya adalah melakukan cache ke file dengan serialisasi.

Tabel memiliki 14355 entri dengan 18 kolom, yaitu tes dan statistik saya tentang membaca cache serial:

JSON:

Seperti yang Anda semua katakan, ketidaknyamanan utama dengan json_encode/ json_decodeadalah bahwa ia mengubah segalanya menjadi sebuah StdClassinstance (atau Object). Jika Anda perlu mengulanginya, mengubahnya menjadi sebuah array adalah apa yang mungkin akan Anda lakukan, dan ya itu meningkatkan waktu transformasi

waktu rata-rata: 780.2 ms; penggunaan memori: 41,5MB; ukuran file cache: 3.8MB

Msgpaket

@ Belanda menyebutkan msgpack . Situs web yang cantik. Mari kita coba.

waktu rata-rata: 497 ms; penggunaan memori: 32MB; ukuran file cache: 2.8MB

Itu lebih baik, tetapi membutuhkan ekstensi baru; mengkompilasi orang yang terkadang takut ...

IgBinary

@GingerDog menyebutkan igbinary . Perhatikan bahwa saya telah mengaturnya igbinary.compact_strings=Offkarena saya lebih peduli tentang kinerja pertunjukan daripada ukuran file.

waktu rata-rata: 411,4 ms; penggunaan memori: 36,75MB; ukuran file cache: 3.3MB

Lebih baik dari paket msg. Namun, ini juga membutuhkan kompilasi.

serialize/unserialize

waktu rata-rata: 477.2 ms; penggunaan memori: 36.25MB; ukuran file cache: 5.9MB

Performa yang lebih baik daripada JSON, semakin besar arraynya, semakin lambat json_decode, tetapi Anda sudah baru itu.

Ekstensi eksternal itu mempersempit ukuran file dan tampak hebat di atas kertas. Angka tidak berbohong *. Apa gunanya mengkompilasi ekstensi jika Anda mendapatkan hasil yang hampir sama dengan fungsi PHP standar?

Kami juga dapat menyimpulkan bahwa tergantung pada kebutuhan Anda, Anda akan memilih sesuatu yang berbeda dari orang lain:

  • IgBinary sangat bagus dan berkinerja lebih baik daripada MsgPack
  • Msgpack lebih baik dalam mengompresi data Anda (perhatikan bahwa saya tidak mencoba opsi igbinary compact.string).
  • Tidak mau dikompilasi? Gunakan standar.

Itu saja, perbandingan metode serialisasi lain untuk membantu Anda memilih satu!

* Diuji dengan PHPUnit 3.7.31, php 5.5.10 - hanya decoding dengan hardrive standar dan CPU dual core lama - angka rata-rata pada 10 tes kasus penggunaan yang sama, statistik Anda mungkin berbeda

soyuka
sumber
Mengapa tidak meneruskan flag ke json_decode untuk memaksa kembali array?
Alex Yaroshevich
Karena lambat. Saya tidak menguji ini tetapi saya berpikir bahwa dengan memaksa perubahan tipe dari php lebih cepat.
soyuka
Saya hanya tahu bahwa membuat array jauh lebih cepat daripada objek di php.
Alex Yaroshevich
Jadi Anda berbicara tentang json_decode($object, true), pada dasarnya itu akan melakukan hal yang sama (array) json_decode($object)tetapi secara rekursif sehingga akan menjadi perilaku yang sama dan itu akan memiliki biaya yang signifikan dalam kedua kasus. Perhatikan bahwa saya belum menguji perbedaan kinerja antara StdClassdan arraytapi itu bukan intinya di sini.
soyuka
Saya yakin itu biaya lain karena dilakukan pada tingkat yang lebih rendah tanpa benda.
Alex Yaroshevich
8

Sepertinya serialisasi adalah yang akan saya gunakan karena 2 alasan:

  • Seseorang menunjukkan bahwa unserialize lebih cepat daripada json_decode dan case 'read' terdengar lebih mungkin daripada case 'write'.

  • Saya mengalami masalah dengan json_encode ketika memiliki string dengan karakter UTF-8 yang tidak valid. Ketika itu terjadi string berakhir menjadi kosong yang menyebabkan hilangnya informasi.

urraka
sumber
dapatkah Anda menjelaskan poin terakhir Anda dengan sebuah contoh
Naveen Saroye
6

Saya telah menguji ini dengan sangat teliti pada hash multi-hash yang cukup kompleks, dengan semua jenis data di dalamnya (string, NULL, integer), dan serialisasi / unserialize berakhir jauh lebih cepat daripada json_encode / json_decode.

Satu-satunya keuntungan yang dimiliki json dalam pengujian saya adalah ukurannya yang 'lebih kecil'.

Ini dilakukan di PHP 5.3.3, beri tahu saya jika Anda ingin lebih detail.

Berikut adalah hasil tes kemudian kode untuk memproduksinya. Saya tidak bisa memberikan data tes karena itu akan mengungkapkan informasi yang saya tidak bisa lepaskan di alam liar.

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!';
}
Tuan Sox
sumber
Saya baru saja melakukan tes serupa dengan PHP 5.4.12 dan menemukan hasil yang serupa: {un,} berserat lebih cepat. Data saya hash bersarang 3 level (900k serial).
sorpigal
6

Saya membuat patokan kecil juga. Hasil saya sama. Tapi aku butuh kinerja decode. Di mana saya perhatikan, seperti beberapa orang di atas katakan juga, unserializelebih cepat daripada json_decode. unserializemembutuhkan sekitar 60-70% dari json_decodewaktu. Jadi kesimpulannya cukup sederhana: Ketika Anda membutuhkan kinerja dalam encoding, gunakan json_encode, ketika Anda membutuhkan kinerja saat decoding, gunakan unserialize. Karena Anda tidak dapat menggabungkan dua fungsi, Anda harus membuat pilihan di mana Anda memerlukan lebih banyak kinerja.

Tolok ukur saya dalam semu:

  • Tentukan array $ arr dengan beberapa kunci dan nilai acak
  • untuk x <100; x ++; serialkan dan json_encode sebuah array_rand dari $ arr
  • untuk y <1000; y ++; json_decode string yang dikodekan json - waktu kalk
  • untuk y <1000; y ++; membatalkan serial string - waktu kalk
  • gema hasil yang lebih cepat

Rata-rata: unserialize menang 96 kali lebih dari 4 kali json_decode. Dengan rata-rata sekitar 1,5 ms lebih dari 2,5 ms.

Jelmer
sumber
3

Sebelum Anda membuat keputusan akhir, perhatikan bahwa format JSON tidak aman untuk array asosiatif - json_decode()sebagai gantinya akan mengembalikannya sebagai objek:

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

Output adalah:

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
terlalu banyak php
sumber
Memang kamu benar. Maksudku, ini notasi objek Javascript ! Untungnya, jika Anda tahu bahwa apa yang Anda enkode menggunakan json_encodeadalah array asosiatif, Anda dapat dengan mudah memaksanya kembali ke dalam array seperti: $json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);Juga baik untuk dicatat bahwa Anda dapat mengakses objek dengan cara yang sama seperti array dalam PHP sehingga dalam skenario yang khas, orang bahkan tidak akan tahu bedanya. Poin yang bagus!
KyleFarris
30
@toomuchphp, maaf tapi Anda salah. Ada parameter kedua untuk json_decode 'bool $ assoc = false' yang membuat json_decode menghasilkan array. @KyleFarris, ini juga harus lebih cepat daripada menggunakan typecast ke array.
janpio
jawabannya tidak benar. saat menggunakan true sebagai parameter fungsi kedua, json_decode () akan mengembalikan array asosiatif alih-alih objek.
Marvin Saldinger
3

Pertama, saya mengubah skrip untuk melakukan lebih banyak pembandingan (dan juga melakukan 1.000 kali alih-alih hanya 1):

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

Saya menggunakan versi PHP 7 ini:

PHP 7.0.14 (cli) (dibangun: Jan 18 2017 19:13:23) (NTS) Hak Cipta (c) 1997-2016 PHP Group Zend Engine v3.0.0, Hak Cipta (c) 1998-2016 Zend Technologies dengan Zend OPcache v7.0.14, Hak Cipta (c) 1999-2016, oleh Zend Technologies

Dan hasil saya adalah:

serialize () (menang: 999) kira-kira 10,98% lebih cepat dari json_encode () unserialize () (menang: 987) kira-kira 33,26% lebih cepat dari json_decode () unserialize () (menang: 987) kira-kira 48,35% lebih cepat dari array json_decode ()

Jadi jelas , serialize / unserialize adalah metode tercepat , sedangkan json_encode / decode adalah yang paling portabel.

Jika Anda mempertimbangkan skenario di mana Anda membaca / menulis data serial 10x atau lebih sering daripada yang perlu Anda kirim atau terima dari sistem non-PHP, Anda MASIH lebih baik menggunakan serialisasi / unserialize dan memilikinya json_encode atau json_decode sebelum serialisasi dalam hal waktu.

Shawn Tolidano
sumber
2

Lihat hasilnya di sini (maaf untuk peretasan yang menempatkan kode PHP di kotak kode JS):

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

HASIL: serialize()dan unserialize()keduanya secara signifikan lebih cepat di PHP 5.4 pada array dengan ukuran yang bervariasi.

Saya membuat skrip uji pada data dunia nyata untuk membandingkan json_encode vs serialize dan json_decode vs unserialize. Tes dijalankan pada sistem caching dari situs e-commerce produksi. Ini hanya mengambil data yang sudah ada dalam cache, dan menguji waktu untuk menyandikan / mendekode (atau membuat serial / unserialize) semua data dan saya memasukkannya ke dalam tabel yang mudah dilihat.

Saya menjalankan ini di server hosting bersama PHP 5.4.

Hasilnya sangat konklusif bahwa untuk kumpulan data besar hingga kecil ini serialisasi dan unserialize adalah pemenang yang jelas. Khususnya untuk kasus penggunaan saya, json_decode dan unserialize adalah yang paling penting untuk sistem caching. Unserialize hampir menjadi pemenang di mana-mana di sini. Itu biasanya 2 hingga 4 kali (kadang-kadang 6 atau 7 kali) secepat json_decode.

Sangat menarik untuk mencatat perbedaan hasil dari @ peter-bailey.

Berikut adalah kode PHP yang digunakan untuk menghasilkan hasil:

<?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>
newms87
sumber
1

just an fyi - jika Anda ingin membuat cerita bersambung data Anda ke sesuatu yang mudah dibaca dan dipahami seperti JSON tetapi dengan lebih banyak kompresi dan kinerja yang lebih tinggi, Anda harus memeriksa paket pesan.

Kandang kelinci
sumber
2
jika itu hanya sebuah fyi, Anda sebaiknya memasukkannya sebagai komentar.
technophyle
0

JSON lebih baik jika Anda ingin membuat cadangan data dan memulihkannya di mesin lain atau melalui FTP.

Misalnya dengan membuat cerita bersambung jika Anda menyimpan data di server Windows, mengunduhnya melalui FTP dan mengembalikannya ke Linux yang tidak dapat berfungsi lagi karena pengkodean ulang charachter, karena membuat cerita bersambung menyimpan panjang string dan dalam Unicode > UTF-8 transcoding beberapa charachter 1 byte bisa menjadi 2 byte membuat algoritma crash.

Informate.it
sumber
0

THX - untuk kode tolok ukur ini:

Hasil saya pada array yang saya gunakan untuk konfigurasi adalah sebagai berikut: JSON disandikan dalam 0,0031511783599854 detik
PHP yang diserialkan dalam 0,0037961006164551 detik
json_encode()kira-kira 20,47% lebih cepat daripada serialize() JSON yang disandikan dalam 0,0070841312408447 detik
PHP yang diserialkan dalam 0,0035839080810547 detik
unserialize()lebih cepat 97,66% daripadajson_encode()

Jadi - uji pada data Anda sendiri.

mk182
sumber
Maksud Anda json_decode () dalam "unserialize () kira-kira 97,66% lebih cepat daripada json_encode ()", ya?
Meezaan-ud-Din
0

Jika untuk meringkas apa yang orang katakan di sini, json_decode / encode tampaknya lebih cepat daripada membuat serial / unserialize TETAPI Jika Anda melakukan var_dump jenis objek serial diubah. Jika karena alasan tertentu Anda ingin tetap menggunakan tipe ini, gunakan serialize!

(coba misalnya stdClass vs array)

cerita bersambung / terbongkar:

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 encode / decode

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]

Seperti yang Anda lihat, json_encode / decode mengubah semua menjadi stdClass, yang tidak terlalu bagus, info objek hilang ... Jadi putuskan berdasarkan kebutuhan, terutama jika bukan hanya array ...

David Constantine
sumber
Hanya sebuah catatan: Sebagian besar jawaban lain mengatakan bahwa serialisasi / unserialize lebih cepat.
Ecker00
-3

Saya akan menyarankan Anda untuk menggunakan Super Cache, yang merupakan mekanisme cache file yang tidak akan menggunakan json_encodeatau serialize. Ini mudah digunakan dan sangat cepat dibandingkan dengan mekanisme PHP Cache lainnya.

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

Ex:

<?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();
?>
Shabeer
sumber
-1. Meskipun ini mungkin solusi yang lebih baik, tidak ada bagian dari jawaban ini yang benar-benar menjawab pertanyaan OP. Di masa depan, mungkin mencoba menjawab pertanyaan tetapi meninggalkan saran di bagian bawah bahwa solusi alternatif mungkin perlu diselidiki.
starbeamrainbowlabs