search:

C++ Json Parser 조사

06 Mar 2012

C++에서 Json을 사용할 일이 생기면서 C++에서 사용 가능한 Json Parser를 조사해 봤습니다.

조사결과 다음과 같은 파서가 존재했으며 간단히 특징을 기술해 보고 테스트 결과를 공유하고자 합니다.

조사 대상

라이브러리명 언어 평가
jsoncpp C++ 큰 무리 없이 사용 가능
janson C 오래되고 안정적
json sprint C++ Boost Sprint library 사용. header only로 설치가 된다던데, 설치가 어려워서 포기함
MongoDB의 json parser C++ MongoDB C++ driver에 내장됨. MongoDB만 설치하면 자동 설치되나 사용 방법이 어려움
Universal Container C++ 원래 목적은 PHP 등 스크립트 언어의 자료 구조를 지원하는 용도이지만, json으로 encode, decode 가능. 설치하는데 고생을 많이했는데, 설치 후에 막상 컴파일하고 돌리는데 Seg. fault가 발생해서 테스트 포기

JsonCPP

  • http://jsoncpp.sourceforge.net/
  • 큰 단점없이 사용 가능.
  • 단, library 빌드 시 -O2 가 안 켜져 있어서 직접 켜줘야 속도가 빠름. 안 그러면 PHP보다 느림.
  • library 소스에서 SConstruct 파일을 열어서 CCFLAGS = "-Wall"-O2를 추가하거나 scons --opt=-O2 주기.
  • key 순서가 알파벳 순서로 바뀌어 출력됨.
{
    "k2":"xxx",
    "k1":"yyy"
}

의 문서 경우, json 문서를 탐색할 때 항상 k1이 먼저 접근됨.

  • key 순서 문제의 경우, 이 문서 를 참고하여 소스를 직접 바꾸면 된다고 하는데 아직 실험적인 방식이라 시도해 보진 못함.
  • UTF-8 문서를 읽는데 문제는 없으나, 출력 시 utf8 문자를 \uxxxx 형태로 출력하는 것은 안 됨. (읽을 때는 가능)
  • 앞으로 지원할 예정이라고 함.
  • http://jsoncpp.sourceforge.net/roadmap.html 여기에 TODO가 정리됨

jansson

  • http://www.digip.org/jansson/
  • 만든지 오래되고 사용하는 곳도 많은 듯.
  • 단, C 언어라서 코딩하기가 귀찮음.
  • C언어로 개발할 때는 jansson을 사용하는게 제일 좋을 듯.
  • utf8 fully support
  • json object간에 reference count를 수동으로 기록할 수 있고, 메모리 관리를 개발자가 직접할 수 있음.
  • 그러나 이를 관리하기 위한 코딩이 좀 수고스러울 듯.

json spirit

  • http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
  • Boost Spirit library를 이용하여 만든 JSON Parser
  • header only로 설치 가능하다고 함.
  • utf8 지원
  • 본인은 library 설치가 잘 안 되고 특별한 장점을 찾기 못해서 더 이상 조사 안 함.

MongoDB의 Json parser

MongoDB의 JSON Parser

  • http://api.mongodb.org/cplusplus/2.0.2/namespacemongo.html#a4f542be0d0f9bad2d8cb32c3436026c2
  • mongodb C++ driver를 다운 받으면, Mongo::fromjson() method.
  • mongodb로 프로젝트를 하는 경우, BSONObj를 다룰 줄 알아야 하므로 json parser로 적당할 수도.
  • 단, 64MB 이상의 경우 parsing 하다가 에러 발생.
  • mongo/bson/util/builder.h 파일을 열어서 BSONObjMaxUserSize, BufferMaxSize의 값을 늘리면 해결 가능함.
  • json 파싱 시간은 느리지만, 메모리 사용량은 다른 것보다 적음. (Bson 형태이므로 압축 효과가 있어서 그럴 듯??)
  • JSON 문서가 항상 object로 시작하고 key가 있어야 함. 이건 좀 불편함.
  • [{...}] <= Object가 아닌 Array여서 오류
  • 다음과 같이 변환해야 함. {"temp":[{...}]}
  • key에 _id가 항상 삽입됨….

UniversalContainer

  • http://greatpanic.com/progdocs/libuc.html
  • 원래 목적은 자료 구조를 PHP, Perl 처럼 쉽게 접근하기 위한 목적임.
  • 자료 구조를 JSON으로 serialize, de-serialize 가능함.
  • FlexLexer.h 파일 문제 때문에 컴파일이 안 되는데 인터넷 찾으면 설치는 가능함.
  • 어렵사리 설치를 했으나, 테스트 해 보면 seg. fault가 많이 발생.
  • 더 이상 테스트 포기
  • 복잡한 자료구조를 담고 사용하는데 편리해 보였는데 테스트 조차 못해서 아쉬움이 큼.
  • 그런데 jsoncpp로 복잡한 자료 구조를 담고 사용하는데 편해서 다행임.

성능 테스트

주의:평가 결과는 각자 환경마다 다를 수 있으니 너무 맹신하진 마세요.

평가 대상

총 5개의 Library 중, 테스트 가능한 다음의 2개 + PHP가 테스트 대상임.

  • jsoncpp
  • janson
  • Mongo::fromjson
  • PHP

평가 환경

  • 입력 파일
  • 파일 사이즈 : 250MB
  • 2차원 array 형.
[
  {....} <= depth 확장 없음.  190만개의 element가 있음.
  ...
  ...
  {....}
]
  • 평가 항목
  • parsing 시간
  • parsing 시 메모리 사용량
  • 탐색 시간 (각 element의 특정 key를 출력)

성능 평가 결과

항목 jsoncpp jansson PHP Mongo::fromjson
Parsing 시간 10초 13초 10초 24초
메모리 사용량 1.4GB 1.3GB 2.5GB 800MB
탐색 시간 13.7초 13.8초 13.4초 N/A

결과에 대한 소고

  • PHP가 생각보다 빠름.
  • 그래도 jsoncpp나 jansson이 더 빠르길 기대했는데 좀 아쉬움..
  • jansson이 약간 느린데 jansson library가 -O2 켜진 상황에서 설치된 것인지 확인 못함.
  • 만약 O2가 아닌 상태로 설치되어서 O2를 킨다고 하면 좀 더 빨라질 수 있으므로 참고.
  • Test에 사용된 JSON 포맷에 따라 결과가 달라질 수 있으므로 유의.