PHP 배열을 저장하는 데 선호되는 방법 (json_encode와 serialize)


609

캐싱을 위해 다차원 연관 데이터 배열을 플랫 파일에 저장해야합니다. 웹 응용 프로그램에서 사용하기 위해 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 문자로 변환).
  • JSON에는 객체의 원래 클래스에 대한 메모리가 없습니다 (항상 stdClass의 인스턴스로 복원됩니다).
  • 당신은 활용할 수 없습니다 __sleep()__wakeup()JSON과
  • 기본적으로 공개 특성 만 JSON으로 직렬화됩니다. ( 이 동작을 변경하기 위해 JsonSerializablePHP>=5.4구현할 수 있습니다 ).
  • 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';
}

31
"JSON은 UTF-8 문자를 유니 코드 이스케이프 시퀀스로 변환합니다." 더 이상 사실 일 필요는 없습니다 JSON_UNESCAPED_UNICODE.
TRiG

32
여기에서 우리는 거의 5 년 후에 테스트를 다시 실행했으며 () 그냥 json_encode직렬화보다 평균 131 % 더 빠릅니다. 따라서 5.4.x에서 5.3.x보다 그 기능이 약간 개선되었습니다. 특히 CentOS 6에서 5.4.24를 실행하고 있습니다.
KyleFarris

8
내 경우에는 우리가 한 번 인코딩을 많이 디코딩, 우리가 때 unserialize를 대 json_decode를 벤치마킹하고 결과를 JSON은 0.093269109725952 초로 <br> json_decode에로 unserialize 0.06662392616272 초로 <br> PHP에 dcoded이었다 그래서 () 약 39.99 %가 때 unserialize보다 빨랐다 ()
AMB

21
흥미있는 : 3v4l.org 에서이 코드를 실행 하면 최신 PHP7 개발 빌드가 json_encode보다 직렬화가 더 빠르게 실행됩니다. "serialize ()가 json_encode ()보다 약 76.53 % 빠릅니다."
marcvangend

21
2017, PHP 7.1 및serialize() was roughly 35.04% faster than json_encode()
Elias Soares

239

JSON 은 PHP의 직렬화 형식보다 간단하고 빠르며 다음과 같은 경우를 제외 하고 사용해야합니다 .

  • 깊이 중첩 된 배열을 저장하고 있습니다. json_decode(): "JSON 인코딩 데이터가 127 개 요소보다 깊은 경우이 함수는 false를 반환합니다."
  • 올바른 클래스로 직렬화 해제 해야하는 객체를 저장하고 있습니다.
  • json_decode를 지원하지 않는 이전 PHP 버전과 상호 작용하고 있습니다.

12
좋은 대답입니다. 하하, 127 층 깊이는 약간 미쳤다. 고맙게도 나는 최대 2-3 명만 가고 있습니다. json_decode / json_encode가 직렬화 해제 / 직렬화보다 빠르다는 사실을 백업 할 데이터가 있습니까?
KyleFarris

1
얼마 전에 테스트했는데 json이 더 빨리 나왔습니다. 더 이상 데이터가 없습니다.
그렉

47
"5.3.0은 옵션 깊이를 추가 기본 재귀 깊이에서 128 512로 증가했다."
giorgio79

4
위의 목록에 하나 이상의 항목을 추가하려고합니다. 데이터에 잘못된 UTF-8 바이트 시퀀스가 ​​포함되어 있으면 json_encode ()를 사용하지 않아야합니다. 그러한 데이터에 대해서는 단순히 false를 반환합니다. 예를 들면 다음과 같습니다. var_dump (json_encode ( "\ xEF \ xEF"));
pako

1
일반적으로 더 빠르다는 것은 사실이 아닙니다. ~ 500 개의 항목이있는 작은 배열이있는 경우 직렬화 해제 / 직렬화는 실제로 json_decode / json_encode (PHP 5.6.19)보다 200-400 % 더 빠릅니다.
Adam

59

이 주제에 대한 블로그 포스트를 작성했습니다 : " 큰 배열을 캐시하십시오 : JSON, serialize 또는 var_export? " . 이 게시물에서는 직렬화가 중소형 어레이에 가장 적합한 선택임을 보여줍니다. 매우 큰 배열 (> 70MB)의 경우 JSON이 더 좋습니다.


8
더 이상 링크를 사용할 수 없습니다.
마틴 토마

1
고마워요, 무스, 링크를 업데이트했습니다. 이 기사는 거의 6 년이되었지만 현재 PHP 버전에서는 정확하지 않을 수 있습니다.
Taco

나는 몇 가지 테스트를했다 및 큰 배열 (사람들을 위해 피터 베일리의 사용 기능)로, 테스트하는 간단한 기능을 만들어 json_encode()관한 150 % 80 % 보다 더 빨리 (그 정말 거기까지 가서) serialize()(300)에 대한 반복과 함께. 그러나 더 작은 배열 ( array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players))))을 사용할 때 750,000 반복으로 테스트 했으며이serialize() 경우 약 6 ~ 10 % 빠릅니다. 내 함수는 모든 반복에 평균 시간이 걸리고 비교됩니다. 여기에 답변 중 하나로 여기에 게시 할 수 있습니다.
MiChAeLoKGB

데이터가 PHP에서만 사용된다면 var_export가 제 것입니다. include 사고에서 가능한 구문 오류에주의해야합니다.
Gfra54

3
블로그가 더 이상 존재하지 않음
popeye

53

PHP에 다른 직렬화 '엔진'을 제공하는 https://github.com/phadej/igbinary에 관심이있을 수도 있습니다 .

64 비트 플랫폼 쇼에서 PHP 5.3.5를 사용하는 임의 / 임의의 '성능'수치 :

JSON :

  • 2.180496931076 초로 인코딩 된 JSON
  • 9.8368630409241 초 안에 JSON 디코딩
  • 직렬화 된 "문자열"크기 : 13993

네이티브 PHP :

  • PHP는 2.9125759601593 초에 직렬화되었습니다.
  • 6.4348418712616 초 내에 PHP 직렬화 해제
  • 직렬화 된 "문자열"크기 : 20769

이그 너리 :

  • WIN 이진이 1.6099879741669 초에 직렬화 됨
  • 4.7737920284271 초 후에 직렬화되지 않은 WIN 이진
  • WIN 직렬화 "문자열"크기 : 4467

따라서 igbinary_serialize () 및 igbinary_unserialize ()가 더 빠르며 디스크 공간을 적게 사용합니다.

위와 같이 fillArray (0, 3) 코드를 사용했지만 배열 키를 더 긴 문자열로 만들었습니다.

igbinary는 PHP의 native serialize can과 동일한 데이터 타입을 저장할 수 있으며 (따라서 객체에 아무런 문제가 없음) 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 인코딩 속도가 더 빠르고 문자열이 더 작지만 직렬화가 빠르면 문자열을 디코딩하는 것이 빠르다는 결론을 내릴 수 있습니다.


6
사람들이 왜 그렇게 작은 데이터 세트로 성능 테스트를 항상 수행하는지 모르겠습니다. 결과에 오류를 발생시키는 모든 오버 헤드가 있습니다. 그리고 사람들이 성능에 관심이 있다면 아마도 마이크로 초를 한 번 얻는 데 아무런 의미가 없기 때문에 데이터 세트가 매우 크기 때문일 것입니다.
Yann Sagon

1
나는 종종 많은 작은 데이터 세트를 반복합니다. 수백 개의 작은 데이터 세트를 사용하면 각각에 대해 1mS를 얻는 것이 여전히 흥미 롭습니다.
Teson

@YannSagon 작은 데이터 집합이 있더라도 성능 테스트를 수행하는 것이 좋습니다. 테스트 전에 약 1 마이크로 초인지 어떻게 알 수 있습니까?
Adam


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

정말 좋은 주제이며 몇 가지 답변을 읽은 후 주제에 대한 실험을 공유하고 싶습니다.

데이터베이스와 대화 할 때마다 거의 "거대한"테이블을 쿼리해야하는 유스 케이스가 있습니다 (이유는 묻지 마십시오). 데이터베이스 캐싱 시스템은 다른 요청을 캐시하지 않으므로 적절하지 않으므로 PHP 캐싱 시스템에 대해서는 설명합니다.

시도 apcu했지만 필요에 맞지 않았 으며이 경우 메모리가 충분하지 않습니다. 다음 단계는 직렬화를 통해 파일로 캐시하는 것입니다.

표에는 열이 18 개인 14355 개의 항목이 있으며, 이는 직렬화 된 캐시를 읽는 데 대한 테스트 및 통계입니다.

JSON :

당신이 말했듯이 json_encode/에 대한 가장 큰 불편 json_decode은 모든 것을 StdClass인스턴스 (또는 객체)로 변환한다는 것 입니다. 루프를 반복 해야하는 경우 배열로 변환하면 아마도 할 일이며, 그래야 변환 시간이 길어집니다.

평균 시간 : 780.2 ms; 메모리 사용 : 41.5MB; 캐시 파일 크기 : 3.8MB

메시지 팩

@hutch는 msgpack을 언급 합니다 . 예쁜 웹 사이트. 시도해 볼까요?

평균 시간 : 497ms; 메모리 사용 : 32MB; 캐시 파일 크기 : 2.8MB

더 낫지 만 새로운 확장이 필요합니다. 때때로 사람들을 두려워하는 편을 ...

이진

@GingerDog는 igbinary를 언급 합니다 . igbinary.compact_strings=Off파일 크기보다 읽기 성능에 더 관심 이 있기 때문에 설정했습니다 .

평균 시간 : 411.4 ms; 메모리 사용 : 36.75MB; 캐시 파일 크기 : 3.3MB

메시지 팩보다 낫습니다. 여전히 이것도 컴파일이 필요합니다.

serialize/unserialize

평균 시간 : 477.2ms; 메모리 사용 : 36.25MB; 캐시 파일 크기 : 5.9MB

JSON보다 성능이 좋을수록 배열이 클수록 느리지 json_decode만 이미 새로운 것입니다.

이러한 외부 확장자는 파일 크기를 좁히고 종이에 적합합니다. 숫자는 거짓말하지 않습니다 *. 표준 PHP 함수와 거의 동일한 결과를 얻는다면 확장을 컴파일하는 요점은 무엇입니까?

또한 필요에 따라 다른 사람과 다른 것을 선택한다고 추론 할 수 있습니다.

  • IgBinary는 MsgPack보다 정말 훌륭하고 성능이 좋습니다.
  • Msgpack은 데이터 압축에 더 좋습니다 (igbinary compact.string 옵션을 시도하지 않았다는 점에 유의하십시오).
  • 컴파일하고 싶지 않습니까? 표준을 사용하십시오.

그게 당신이 하나를 선택하는 데 도움이되는 또 다른 직렬화 방법 비교입니다!

* PHPUnit 3.7.31, php 5.5.10으로 테스트-표준 hardrive 및 기존 듀얼 코어 CPU로만 디코딩-10 개의 동일한 사용 사례 테스트에서 평균 수치, 통계는 다를 수 있음


배열을 강제로 반환하기 위해 플래그를 json_decode에 전달하지 않는 이유는 무엇입니까?
Alex Yaroshevich

느리기 때문입니다. 나는 이것을 테스트하지 않았지만 단순히 PHP에서 유형 변경을 강제하는 것이 더 빠르다고 생각합니다.
soyuka

PHP에서 객체보다 훨씬 빠르게 배열을 생성한다는 것을 알고 있습니다.
Alex Yaroshevich

에 대해 이야기하고 있습니다 json_decode($object, true). 기본적으로 (array) json_decode($object)동일한 동작이지만 재귀 적으로 수행되므로 동일한 동작이되며 두 경우 모두 상당한 비용이 발생합니다. 나는 사이의 성능 차이점을 테스트하지 않았 음을 참고 StdClass하고 array있지만, 여기의 정말 지점 것을.
soyuka

객체없이 낮은 수준에서 수행되기 때문에 추가 비용이 발생합니다.
Alex Yaroshevich

8

serialize가 두 가지 이유로 사용하려는 것 같습니다.

  • 누군가 직렬화 해제가 json_decode보다 빠르며 '읽기'케이스는 '쓰기'케이스보다 더 가능성이 높다고 지적했습니다.

  • UTF-8 문자가 잘못된 문자열을 사용할 때 json_encode에 문제가 있습니다. 이 경우 문자열이 비워져 정보가 유실됩니다.


예를 들어 마지막 요점을 자세히
설명해 주시겠습니까

6

나는 모든 종류의 데이터 (문자열, NULL, 정수)가있는 상당히 복잡하고 약간 중첩 된 멀티 해시에서 이것을 철저히 테스트했으며 직렬화 / 직렬화 해제는 json_encode / json_decode보다 훨씬 빠릅니다.

내 테스트에서 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,} 직렬화가 더 빠릅니다. 내 데이터는 3 레벨 깊이 중첩 된 해시입니다 (900k 직렬화).
sorpigal

6

작은 벤치 마크도 만들었습니다. 내 결과는 동일했다. 그러나 디코딩 성능이 필요합니다. 위의 몇몇 사람들이 말한 것처럼 내가 알아 차린 곳 unserialize은보다 빠릅니다 json_decode. unserialize대략 60-70 %의json_decode 시간 걸립니다. 따라서 결론은 매우 간단합니다. 인코딩 성능이 필요할 때는을 사용 json_encode하고 디코딩 할 때 성능이 필요할 때는을 사용하십시오 unserialize. 두 기능을 병합 할 수 없으므로 성능이 더 필요한 곳을 선택해야합니다.

의사 내 벤치 마크 :

  • 임의의 키와 값으로 배열 $ arr 정의
  • x <100의 경우; x ++; $ arr의 array_rand를 직렬화하고 json_encode
  • y <1000의 경우; y ++; json_decode JSON 인코딩 문자열-계산 시간
  • y <1000의 경우; y ++; 직렬화 된 문자열을 직렬화 해제-계산 시간
  • 더 빠른 결과를 에코

avarage에서 : 직렬화 해제는 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
)

사실, 당신 말이 맞아요. 나는 그것이 의미 입니다 자바 스크립트 객체 Afterall는 표기! 고맙게도 사용하여 인코딩 한 것이 연관 배열 이라는 것을 알고 있다면 다음 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'에 대한 두 번째 매개 변수가 있습니다. @KyleFarris, typecast를 사용하여 배열하는 것보다 빠릅니다.
janpio

답이 맞지 않습니다. 함수의 두 번째 매개 변수로 true를 사용하면 json_decode ()는 객체 대신 연관 배열을 반환합니다.
Marvin Saldinger

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) (built : 2017 년 1 월 18 일 19:13:23) (NTS) Copyright (c) 1997-2016 PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend OPcache를 사용한 Zend Technologies v7.0.14, Copyright (c) 1999-2016, Zend Technologies

그리고 내 결과는 다음과 같습니다.

serialize () (wins : 999)는 json_encode ()보다 대략 10.98 % 빠릅니다. unserialize () (wins : 987)는 json_decode ()보다 대략 33.26 % 빠릅니다. ()

그래서 명확하게 , 직렬화가 / 때 unserialize는 것입니다 가장 빠른 로 json_encode / 디코드가있는 동안, 방법 대부분의 휴대용.

비 PHP 시스템으로 보내거나받는 것보다 10 배 이상 직렬화 된 데이터를 읽거나 쓰는 시나리오를 고려할 경우 직렬화 / 비 직렬화를 사용하고 직렬화 전에 json_encode 또는 json_decode를 사용하는 것이 좋습니다. 시간의 관점에서.


2

여기에서 결과를 확인하십시오 (JS 코드 상자에 PHP 코드를 넣는 해킹에 대해 죄송합니다).

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

결과 : serialize()unserialize()다양한 크기의 배열에 훨씬 빠르게 PHP 5.4의 상표입니다.

json_encode vs serialize와 json_decode vs unserialize를 비교하기 위해 실제 데이터에 대한 테스트 스크립트를 만들었습니다. 테스트는 프로덕션 전자 상거래 사이트의 캐싱 시스템에서 실행되었습니다. 단순히 캐시에있는 데이터를 가져 와서 모든 데이터를 인코딩 / 디코딩 (또는 직렬화 / 직렬화 해제)하는 시간을 테스트하여 쉽게 볼 수있는 테이블에 넣습니다.

PHP 5.4 공유 호스팅 서버에서 이것을 실행했습니다.

결과는 이러한 크고 작은 데이터 세트의 경우 직렬화 및 직렬화 해제가 확실한 승자라는 결론을 내 렸습니다. 특히 사용 사례의 경우 캐싱 시스템에서 json_decode 및 직렬화 해제가 가장 중요합니다. 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

간단히 말해-데이터를 JSON처럼 읽고 이해하기 쉬운 것으로 압축하지만 더 높은 압축 성능을 가진 데이터로 직렬화하려면 메시지 팩을 확인해야합니다 .


2
그것이 단지 fyi라면, 주석으로 쓰는 것이 좋습니다.
technophyle

0

데이터를 백업하고 다른 머신이나 FTP를 통해 복원하려는 경우 JSON이 더 좋습니다.

예를 들어, Windows 서버에 데이터를 저장하는 경우 직렬화를 사용하는 경우 FTP를 통해 데이터를 다운로드하고 Linux에서 복원하면 charachter re-encoding으로 인해 더 이상 작동하지 않습니다. > UTF-8 트랜스 코딩으로 인해 1 바이트 문자가 2 바이트가되어 알고리즘 충돌이 발생할 수 있습니다.


0

THX-이 벤치 마크 코드의 경우 :

구성에 사용하는 배열의 결과는 다음과 같습니다. 0.0031511783599854 초로 인코딩 된 JSON 0.0037961006164551 초로
직렬화 된 PHP는 0.0070841312408447 초로 인코딩 된 JSON
json_encode()보다 약 20.47 % 빠릅니다 serialize()0.0035839080810547 초로
직렬화 된 PHP
unserialize()는 약 97.66 % 빠릅니다.json_encode()

따라서 자신의 데이터로 테스트하십시오.


"unserialize ()의 json_decode ()가 json_encode ()보다 약 97.66 % 빠르다"는 것을 의미합니까?
Meezaan-ud-Din

0

사람들이 여기서 말하는 것을 요약하면 json_decode / encode는 serialize / unserialize보다 빠릅니다. 그러나 var_dump를 수행하면 serialize 된 객체의 유형이 변경됩니다. 어떤 이유로 유형을 유지하려면 serialize로 이동하십시오!

(예를 들어 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

난 당신이 사용하지 않는 파일 캐시 메커니즘 슈퍼 캐시 사용하는 제안 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.