2013/05/28

Recent entries from same category

  1. C++ で STL フレンドリに扱えるJSONパーサ「json.hpp」
  2. SSE を使わなくても HTML エスケープはある程度速くできる。
  3. glib を使ったマイクロフレームワーク「balde」
  4. ODBC 接続なアプリケーションの開発が楽になる C++ ライブラリ nanodbc
  5. SQLite3でカジュアルにズンドコキヨシ

なんびとたりとも俺の前は走らせねぇ
ガチバトルです。
rapidjson - A fast JSON parser/generator for C++ with both SAX/DOM style API - Google Project Hosting

Rapidjson is an attempt to create the fastest JSON parser and generator. Small but complete. Support...

https://code.google.com/p/rapidjson/
fastest をうたうとは度胸があるなーと思いながら、半信半疑で試してみました。
rapidjson も picojson 同様に、ヘッダファイルだけあればコンパイル出来る C++ 向け JSON パーサ(およびシリアライザ)です。
まずは rapidjson を使ったコード。
#include <rapidjson/document.h>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <time.h>

int
main(int argc, char* argv[]) {
  clock_t t;
  t = clock();
  for (int n = 0; n < 1000; n++) {
    std::stringstream ss;
    std::ifstream f;
    f.open("foo.json", std::ios::binary);
    ss << f.rdbuf();
    f.close();

    rapidjson::Document doc;  
    if (doc.Parse<0>(ss.str().c_str()).HasParseError()) {
      std::cerr << "parse error" << std::endl;
      return 1;
    }

    rapidjson::Value& entries = doc["entries"];
    int i, l = entries.Size();
    for (i = 0; i < l; i++) {
      std::cerr << entries[rapidjson::SizeType(i)]["title"].GetString() << std::endl;
    }
  }
  std::cout << "score: " << clock() - t << std::endl;
  return 0;
}
そして picojson を使ったコード
#include <picojson.h>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <time.h>

int
main(int argc, char* argv[]) {
  clock_t t;
  t = clock();
  for (int n = 0; n < 1000; n++) {
    std::stringstream ss;
    std::ifstream f;
    f.open("foo.json", std::ios::binary);
    ss << f.rdbuf();
    f.close();

    picojson::value v; ss >> v;
    picojson::array a = v.get<picojson::object>()["entries"].get<picojson::array>();
    int i, l = a.size();
    for (i = 0; i < l; i++) {
      std::cerr << a[i].get<picojson::object>()["title"].to_str() << std::endl;
    }
  }
  std::cout << "score: " << clock() - t << std::endl;
  return 0;
}
picojson については、std::for_each を使っても見たけど結局自前ループで回した方が速い結果になりました。

コンパイルは両者とも
g++ -std=c++11 -O2 foo.cxx
でやりました。
読み込んでる JSON はこれを使いました。ウチのサイトの JSON 形式のフィードです。やってる内容は
  • ファイルを読み込む
  • パースする
  • entries の一覧を取る
  • 各 title の内容を標準エラーに出力する
これを1000回実行します。標準エラーは捨てながら計測しました。

結果は以下の通り。
rapidjson score: 3559
picojson score: 7961
こうなりました。picojson と比べて rapidjson がほぼ2倍速いという結果になりました。速い理由をソースを見ながら調べてみましたが、rapidjson は STL を使わず、自前で DOM ライクな API を提供しています。また std::string なども使いません。これによってオーバーヘッドを最小限に抑えているのだと思います。
もちろん、picojson の STL フレンドリも僕は好きですし、他の C++ ライブラリと連携する際にも便利です。

Performance - rapidjson - Compares some performance benchmark results of rapidjson 0.1 and other parsers. Also gives some analysis. - A fast JSON parser/generator for C++ with both SAX/DOM style API - Google Project Hosting

Why rapidjson is fast? rapidjson has made use of several techniques to achieve high performance. C++...

https://code.google.com/p/rapidjson/wiki/Performance
それどころか、このスコア表を見ると picojson のスコアは素晴らしいレベルだと分かりました。
唯一難点として rapidjson は確かに速いのですが、パースエラー詳細に取る方法が分かりませんでした。(あるのかもしれません。知ってる人いたら教えて下さい)

という事で、これからも picojson 使って行こうと思います。

blog comments powered by Disqus