PHP arrays को स्टोर करने के लिए पसंदीदा विधि(json_encode बनाम serialize)




performance serialization (12)

THX - इस बेंचमार्क कोड के लिए:

कॉन्फ़िगरेशन के लिए उपयोग किए जाने वाले सरणी पर मेरे परिणाम फेलो के रूप में हैं: JSON 0.0031511783599854 सेकंड में एन्कोड किया गया
PHP 0.0037961006164551 सेकंड में serialized
json_encode() serialize() से लगभग 20.47% तेज serialize() JSON 0.0070841312408447 सेकंड में एन्कोड किया गया
PHP 0.0035839080810547 सेकंड में serialized
unserialize() json_encode() से लगभग 97.66% तेज था

तो - इसे अपने डेटा पर परीक्षण करें।

मुझे कैशिंग उद्देश्यों के लिए एक फ्लैट फ़ाइल में डेटा की बहु-आयामी सहयोगी सरणी को स्टोर करने की आवश्यकता है। मैं कभी-कभी अपने वेब ऐप में उपयोग के लिए जेएसओएन में परिवर्तित करने की ज़रूरत को पूरा कर सकता हूं लेकिन अधिकांश समय मैं सीधे PHP में सरणी का उपयोग कर रहा हूं।

क्या यह सरणी को JSON के रूप में या इस पाठ फ़ाइल में PHP क्रमबद्ध सरणी के रूप में स्टोर करने के लिए अधिक कुशल होगा? मैंने चारों ओर देखा है और ऐसा लगता है कि PHP (5.3) के नवीनतम संस्करणों में, json_decode से वास्तव में तेज़ है।

मैं वर्तमान में जेएसओएन के रूप में सरणी को संग्रहीत करने की ओर झुका रहा हूं क्योंकि यदि आवश्यक हो तो मुझे मानव द्वारा पढ़ना आसान लगता है, इसका उपयोग PHP और जावास्क्रिप्ट दोनों में बहुत कम प्रयास के साथ किया जा सकता है, और जो मैंने पढ़ा है, वह भी हो सकता है डीकोड करने के लिए तेज़ (हालांकि एन्कोडिंग के बारे में निश्चित नहीं है)।

क्या किसी को किसी भी नुकसान के बारे में पता है? किसी भी विधि के प्रदर्शन लाभ दिखाने के लिए किसी के पास अच्छे मानक हैं?


अपना अंतिम निर्णय लेने से पहले, ध्यान रखें कि जेएसओएन प्रारूप सहयोगी सरणी के लिए सुरक्षित नहीं है - 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
)

आपको https://github.com/phadej/igbinary में रुचि भी हो सकती है - जो PHP के लिए एक अलग धारावाहिक 'इंजन' प्रदान करता है।

64 बिट प्लेटफार्म शो पर PHP 5.3.5 का उपयोग करके, मेरा यादृच्छिक / मनमाना 'प्रदर्शन' आंकड़ा:

जेएसओएन:

  • JSON 2.180496931076 सेकंड में एन्कोड किया गया
  • JSON 9.8368630409241 सेकंड में डीकोड किया गया
  • धारावाहिक "स्ट्रिंग" आकार: 13 993

मूल PHP:

  • PHP 2.9125759601593 सेकंड में serialized
  • PHP 6.4348418712616 सेकंड में unserialized
  • धारावाहिक "स्ट्रिंग" आकार: 2076 9

Igbinary:

  • WIN igbinary 1.6099879741669 सेकंड में serialized
  • 4.7737 9 20284271 सेकेंड में अनगिनत रूप से असुरक्षित
  • विन सीरियलाइज्ड "स्ट्रिंग" आकार: 4467

तो, यह igbinary_serialize () और igbinary_unserialize () के लिए तेज़ है और कम डिस्क स्थान का उपयोग करता है।

मैंने उपरोक्त के रूप में fillArray (0, 3) कोड का उपयोग किया, लेकिन सरणी कुंजियों को लंबे तार बना दिया।

igbinary उसी डेटा प्रकारों को स्टोर कर सकता है जैसे कि PHP के देशी धारावाहिक कर सकते हैं (इसलिए ऑब्जेक्ट्स के साथ कोई समस्या नहीं है) और यदि आप चाहें तो सत्र प्रबंधन के लिए इसका उपयोग करने के लिए PHP5.3 बता सकते हैं।

यह भी http://ilia.ws/files/zendcon_2010_hidden_features.pdf - विशेष रूप से 14/15/16 स्लाइड करता है


ऐसा लगता है कि धारावाहिक एक ऐसा है जिसे मैं 2 कारणों से उपयोग करने जा रहा हूं:

  • किसी ने इंगित किया कि unsonialize json_decode से तेज़ है और 'रीड' केस 'लिखने' केस से अधिक संभावित लगता है।

  • अमान्य यूटीएफ -8 अक्षरों के साथ तार होने पर मुझे json_encode के साथ परेशानी हुई है। जब ऐसा होता है तो स्ट्रिंग समाप्त हो जाती है जिससे सूचना का नुकसान होता है।


मैंने अनियमितता प्रदर्शन को शामिल करने के लिए परीक्षण में वृद्धि की। मुझे मिली संख्याएं यहां दी गई हैं।

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, serialize या var_export? "। इस पोस्ट में यह दिखाया गया है कि छोटे से बड़े आकार के सरणी के लिए धारावाहिक सबसे अच्छा विकल्प है। बहुत बड़े सरणी (> 70 एमबी) के लिए जेएसओएन बेहतर विकल्प है।


मैंने एक छोटा बेंचमार्क भी बनाया। मेरे परिणाम एक ही थे। लेकिन मुझे डीकोड प्रदर्शन की ज़रूरत है। जहां मैंने देखा, ऊपर दिए गए कुछ लोगों की तरह भी, unserialize json_decode से तेज है। unserialize json_decode समय के लगभग 60-70% लेता है। तो निष्कर्ष काफी सरल है: जब आपको एन्कोडिंग में प्रदर्शन की आवश्यकता होती है, तो जब आप डीकोडिंग करते समय प्रदर्शन की आवश्यकता होती है, तो json_encode उपयोग unserialize , unserialize उपयोग unserialize । क्योंकि आप दो कार्यों को मर्ज नहीं कर सकते हैं जिन्हें आपको एक choise बनाना है जहां आपको अधिक प्रदर्शन की आवश्यकता है।

छद्म में मेरा बेंचमार्क:

  • कुछ यादृच्छिक कुंजी और मानों के साथ सरणी $ arr परिभाषित करें
  • एक्स <100 के लिए; एक्स ++; serialize और json_encode $ arr का array_rand
  • वाई <1000 के लिए; y ++; json_decode जेसन एन्कोडेड स्ट्रिंग - कैल्क टाइम
  • वाई <1000 के लिए; y ++; serialized स्ट्रिंग - कैल्क समय unserialize
  • परिणाम तेजी से गूंजें जो तेजी से था

अवतार पर: unssonialize json_decode 4 गुणा से 96 गुना जीता। 2.5ms से अधिक 1.5 मिमी के उत्थान के साथ।


यदि आप जानकारी कैश कर रहे हैं कि आप आखिरकार बाद में "शामिल" करना चाहते हैं, तो आप var_export का उपयोग करने का प्रयास करना var_export । इस तरह आप केवल "serialize" में हिट लेते हैं और "unserialize" में नहीं।


यहां परिणाम देखें (जेएस कोड बॉक्स में PHP कोड डालने वाले हैक के लिए खेद है):

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

परिणाम: serialize() और unserialize() दोनों अलग-अलग आकार के सरणी पर PHP 5.4 में काफी तेजी से हैं।

मैंने json_encode बनाम serialize और json_decode बनाम unserialize की तुलना करने के लिए असली दुनिया डेटा पर एक टेस्ट स्क्रिप्ट बनाई। परीक्षण ई-कॉमर्स साइट में कैशिंग सिस्टम पर कैशिंग सिस्टम पर चलाया गया था। यह केवल कैश में पहले से ही डेटा लेता है, और सभी डेटा को एनकोड / डीकोड (या क्रमबद्ध / अनसुलझा) करने के लिए परीक्षण करता है और मैंने इसे तालिका को देखने में आसान बना दिया।

मैं इसे PHP 5.4 साझा होस्टिंग सर्वर पर चलाया।

परिणाम बहुत निर्णायक थे कि इन बड़े से छोटे डेटा सेटों के लिए धारावाहिक और अनिश्चितता स्पष्ट विजेताओं थे। विशेष रूप से मेरे उपयोग के मामले के लिए, json_decode और unserialize कैशिंग सिस्टम के लिए सबसे महत्वपूर्ण हैं। Unserialize यहां लगभग एक सर्वव्यापी विजेता था। यह आम तौर पर 2 से 4 गुना (कभी-कभी 6 या 7 गुना) जितना तेज़ json_decode था।

@ पीटर-बेली के परिणामों में अंतर को ध्यान में रखना दिलचस्प है।

यहां परिणाम उत्पन्न करने के लिए उपयोग किया गया 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>

वाई ने सिर्फ धारावाहिक और जेसन एन्कोड और डीकोड का परीक्षण किया, साथ ही यह आकार स्ट्रिंग को ले जाएगा।

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 तेज़ी से एन्कोड करता है और एक छोटी स्ट्रिंग का परिणाम देता है, लेकिन स्ट्रिंग को डीकोड करने के लिए अनसुलझा करना तेज़ होता है।


सबसे पहले, मैंने स्क्रिप्ट को कुछ और बेंचमार्किंग करने के लिए बदल दिया (और केवल 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 (क्ली) (बनाया गया: 18 जनवरी 2017 1 9:13:23) (एनटीएस) कॉपीराइट (सी) 1997-2016 PHP समूह ज़ेंड इंजन v3.0.0, कॉपीराइट (सी) 1998-2016 ज़ेंड ओपेकैच के साथ ज़ेंड टेक्नोलॉजीज v7.0.14, कॉपीराइट (सी) 1999-2016, ज़ेंड टेक्नोलॉजीज द्वारा

और मेरे परिणाम थे:

serialize () (जीत: 99 9) json_encode () (uninsialize () (जीत: 987) की तुलना में मोटे तौर पर 10.98% तेज था json_decode () unserialize () (जीत: 987) की तुलना में लगभग 33.26% तेज था सरणी json_decode की तुलना में लगभग 48.35% तेज था ()

तो स्पष्ट रूप से , serialize / unserialize सबसे तेज़ तरीका है, जबकि json_encode / decode सबसे पोर्टेबल है।

यदि आप किसी ऐसे परिदृश्य पर विचार करते हैं जहां आप एक गैर-PHP सिस्टम से भेजने या प्राप्त करने की आवश्यकता से अधिक क्रमशः सीरियलाइज्ड डेटा 10x या लिखते हैं, तो आप क्रमशः serialize / unserialize का उपयोग करने के लिए बेहतर हैं और इसे serialization से पहले json_encode या json_decode है समय के संदर्भ में।


सिर्फ एक fyi - यदि आप JSON की तरह पढ़ने और समझने में आसान कुछ डेटा को क्रमबद्ध करना चाहते हैं लेकिन अधिक संपीड़न और उच्च प्रदर्शन के साथ, आपको msgpack देखना चाहिए msgpack





serialization