開源項目 rapidjson

292 views
Skip to first unread message

Milo Yip

unread,
Nov 18, 2011, 1:40:06 PM11/18/11
to TopLanguage
http://code.google.com/p/rapidjson/

一直都沒能成功把一些代碼開源。這次嘗試做點盡量簡單的,工作上又可能用到的,所以就寫了一個JSON庫。

rapidjson是一個高性能的C++ JSON
parser和generator,提供SAX/DOM風格的API,支持UTF8/16/32,可選用SSE2/SSE4.2加速,內存使用緊湊。全個庫只有1600多行代碼的頭文件。

在性能方面,rapidjson受rapidxml啟發(從名字也能想到吧),支持in-situ
parsing。這是指會把字符串的解碼直接寫到源字符串去。我比較了其他兩個C/C++ JSON parser,這裡只寫一點數據,有空再整理。

在VC2010的一個測試中,parse一個672KB的JSON文件至DOM,rapidjson 730μs,YAJL
6149μs,JsonCpp 6680μs,而strlen()也需要495μs。能夠接近strlen()的速度應該算是不錯,但這和VC2010的strlen()性能較差也有關係。cygwin中跑gcc的strlen()只需189μs。

性能源於幾方面,in-situ parsing、用SSE4.2跳過whitespace,使用lookup table計算pow10(int
x)等等。另外還有C++的強項,我使用template進行功能的組合,沒有虛函數的多態,也充分利用到inline的好處。

在VC2010中跳過1M個whitespace,strspn()要3074μs,而SSE4.2加速後只需100μs。這段代碼對很多項目都能使用。

另外,原本能選用C++ exception,後來加入setjmp/longjmp後,覺得完全沒需要使用exception,這方面也能提高少量的性能。

預設的內存allocator是只分配不釋放的,而且parsing時特別設計過,不會產生如std::vector::push_back()時的copy及內存浪費。每個JSON
value在32-bit/64-bit系統中分別佔16及20 bytes(不含字符串)。

設計上提取了一些concept去組合不同功能。例如Reader會從實現了Stream
concept的類讀取字符,之後parse時,把事件傳送給實現了Handler
concept的類。例如PrettyWritter實現了Handler,而產生JSON文本的流,那麼把二者聯合使用:

Reader reader;
FileStream is(stdin);

// Prepare writer and output stream.
FileStream os(stdout);
PrettyWriter<FileStream> writer(os);

// JSON reader parse from the input stream and let writer generate the output.
if (!reader.Parse<0>(is, writer))
fprintf(stderr, "\nError(%u): %s\n",
(unsigned)reader.GetErrorOffset(), reader.GetParseError());

就能validate及"beautify" JSON 文本。

在rapidjson中,Document是用來實現DOM風格的API。特別之處是它能遍歷自己去產生Handler的事件。所以用以下代碼可以把一個Document聯結PrettyWriter把內容寫成JSON文本的流:

Document document;
document.Parse<0>(json);

// modify document ...

FileStream f(stdout);
PrettyWriter<FileStream> writer(f);
document.Accept(writer); // Accept() traverses the DOM and generates
Handler events.


小弟第一次做開源項目,希望大家能用得著,也多給意見。

--
Milo Yip

http://www.cnblogs.com/miloyip/
http://weibo.com/miloyip/
http://twitter.com/miloyip/

翁翊成

unread,
Nov 18, 2011, 10:40:15 PM11/18/11
to pon...@googlegroups.com
开源项目现在更流行使用github,方便其他感兴趣的人参与并贡献代码。

2011/11/19 Milo Yip <mil...@gmail.com>



--
翁翊成

马博文

unread,
Nov 18, 2011, 11:58:13 PM11/18/11
to pon...@googlegroups.com
应该附上连接啊,www.github.com

shiwei xu

unread,
Nov 19, 2011, 10:12:55 AM11/19/11
to pon...@googlegroups.com
非常实用的一个库。:)
我个人也推荐用 github.com 作为 hosting,比 google code 有更好的社区支持,比如他人可以请求合并修改的代码到主干。

2011/11/19 Milo Yip <mil...@gmail.com>



--
许式伟

Milo Yip

unread,
Nov 19, 2011, 10:24:48 AM11/19/11
to TopLanguage
今天寫了一篇rapidjson的性能比較,及分析背後原因的文檔

http://code.google.com/p/rapidjson/wiki/Performance

至於github,鑑於本人不懂Git,可能留待他日再作轉移。

我有空會繼續寫使用手冊、內存比較、設計等文檔。

希望各位多給意見。

Bill Hsu

unread,
Nov 19, 2011, 11:30:25 AM11/19/11
to pon...@googlegroups.com
谢谢Milo分享!
考完期末仔细研究一下。
 
Best,
Bill Hsu




2011/11/19 Milo Yip <mil...@gmail.com>

HaoPeiQiang

unread,
Nov 19, 2011, 9:05:01 PM11/19/11
to pon...@googlegroups.com
很赞,虽然我的项目里面json解析效率不重要

2011/11/20 Bill Hsu <bill...@gmail.com>



--
Tinyfool的Blog http://tiny4.org/blog/

朱金灿

unread,
Nov 26, 2011, 6:05:54 AM11/26/11
to pon...@googlegroups.com
json主要用于网络传输吧,如果作为配置文件,它比起xml文件的优势是什么?

翁翊成

unread,
Nov 26, 2011, 10:25:39 AM11/26/11
to pon...@googlegroups.com
没见过用json当配置文件的。


2011/11/26 朱金灿 <clev...@gmail.com>

windstorm

unread,
Nov 26, 2011, 10:31:05 AM11/26/11
to pon...@googlegroups.com
用json当配置文件的多了去了。

配置文件的特点不外乎这几点,轻便简单易读,能跨平台跨语言,支持unicode编码。json是唯一完美支持这几个特性的。

----------------------------------------------------------------------------------
Yours Sincerely
Kun

gplus.to/kunli


2011/11/26 翁翊成 <wen...@gmail.com>:

Tux9

unread,
Nov 26, 2011, 6:03:40 PM11/26/11
to pon...@googlegroups.com
json一点都不简单易读

那你说说xml和直接A=b这两种配置文件,相比缺点是什么

2011/11/26 windstorm <likunar...@gmail.com>

qiaojie

unread,
Nov 27, 2011, 12:51:33 AM11/27/11
to pon...@googlegroups.com
json比xml简洁,解析起来也简单,用来做配置文件或者序列化可阅读的对象都是很好的选择。


2011/11/26 翁翊成 <wen...@gmail.com>

Tux9

unread,
Nov 27, 2011, 7:02:35 AM11/27/11
to pon...@googlegroups.com
大部分配置文件都不会频繁读写,所以简洁没用,解析简单也用处不大(反正有现成的包),每次读写多点CPU周期和磁盘读写跟本不影响那可以忽略的执行时间。人肉读写简单才是王道

2011/11/27 qiaojie <qia...@gmail.com>

zhang3

unread,
Nov 27, 2011, 7:07:50 AM11/27/11
to pon...@googlegroups.com
还是用小型的函数式脚本语言做配置更能满足各种复杂的要求。

Lich_Ray

unread,
Nov 27, 2011, 7:15:35 AM11/27/11
to pon...@googlegroups.com
On Sun, Nov 27, 2011 at 6:07 AM, zhang3 <open...@gmail.com> wrote:
还是用小型的函数式脚本语言做配置更能满足各种复杂的要求。

其中 lisp 风格的十分好用。如果是用 guile 一类扩展的话还能嵌入一些逻辑。

--
Zhihao Yuan, nickname Lich_Ray
God is in his heaven, all's right with the world.
-------------------------------------------------
let focus = 'computing' in where:
http://lichray.javaeye.com
let focus = 'computing' in here:
http://let-in.blogspot.com

missdeer

unread,
Nov 28, 2011, 1:52:26 AM11/28/11
to TopLanguage
Mark~这个有意思,晚上回去看看能不能合到自己的程序中去~~

On Nov 19, 2:40 am, Milo Yip <milo...@gmail.com> wrote:
> http://code.google.com/p/rapidjson/
>
> 一直都沒能成功把一些代碼開源。這次嘗試做點盡量簡單的,工作上又可能用到的,所以就寫了一個JSON庫。
>
> rapidjson是一個高性能的C++ JSON

> parser和generator,提供SAX/DOM風格的API,支持UTF8/16/32,可選用SSE2/SSE4.2加速,內存使用緊湊。全個庫只有-1600多行代碼的頭文件。


>
> 在性能方面,rapidjson受rapidxml啟發(從名字也能想到吧),支持in-situ
> parsing。這是指會把字符串的解碼直接寫到源字符串去。我比較了其他兩個C/C++ JSON parser,這裡只寫一點數據,有空再整理。
>
> 在VC2010的一個測試中,parse一個672KB的JSON文件至DOM,rapidjson 730μs,YAJL

> 6149μs,JsonCpp 6680μs,而strlen()也需要495μs。能夠接近strlen()的速度應該算是不錯,但這和VC2010的strlen()性能較差也有關係。c-ygwin中跑gcc的strlen()只需189μs。


>
> 性能源於幾方面,in-situ parsing、用SSE4.2跳過whitespace,使用lookup table計算pow10(int
> x)等等。另外還有C++的強項,我使用template進行功能的組合,沒有虛函數的多態,也充分利用到inline的好處。
>
> 在VC2010中跳過1M個whitespace,strspn()要3074μs,而SSE4.2加速後只需100μs。這段代碼對很多項目都能使用。
>
> 另外,原本能選用C++ exception,後來加入setjmp/longjmp後,覺得完全沒需要使用exception,這方面也能提高少量的性能。
>

> 預設的內存allocator是只分配不釋放的,而且parsing時特別設計過,不會產生如std::vector::push_back()時的copy及-內存浪費。每個JSON


> value在32-bit/64-bit系統中分別佔16及20 bytes(不含字符串)。
>
> 設計上提取了一些concept去組合不同功能。例如Reader會從實現了Stream
> concept的類讀取字符,之後parse時,把事件傳送給實現了Handler
> concept的類。例如PrettyWritter實現了Handler,而產生JSON文本的流,那麼把二者聯合使用:
>
> Reader reader;
> FileStream is(stdin);
>
> // Prepare writer and output stream.
> FileStream os(stdout);
> PrettyWriter<FileStream> writer(os);
>
> // JSON reader parse from the input stream and let writer generate the output.
> if (!reader.Parse<0>(is, writer))
> fprintf(stderr, "\nError(%u): %s\n",
> (unsigned)reader.GetErrorOffset(), reader.GetParseError());
>
> 就能validate及"beautify" JSON 文本。
>

> 在rapidjson中,Document是用來實現DOM風格的API。特別之處是它能遍歷自己去產生Handler的事件。所以用以下代碼可以把一個Doc-ument聯結PrettyWriter把內容寫成JSON文本的流:

Zhangming Niu

unread,
Nov 28, 2011, 9:43:59 AM11/28/11
to pon...@googlegroups.com
宝马比起奔驰的优势是什么。。。
 
2011/11/28 missdeer <miss...@gmail.com>
--
--------------------------------------------------------------------
Best Regards,

Zhangming Niu




missdeer

unread,
Nov 28, 2011, 8:08:53 PM11/28/11
to TopLanguage
没有两种车都开过一段时间,谁能说出到底各有什么优缺点。。。

On Nov 28, 10:43 pm, Zhangming Niu <niuzhangm...@gmail.com> wrote:
> 宝马比起奔驰的优势是什么。。。
>
> 2011/11/28 missdeer <missd...@gmail.com>


>
>
>
>
>
> > Mark~这个有意思,晚上回去看看能不能合到自己的程序中去~~
>
> > On Nov 19, 2:40 am, Milo Yip <milo...@gmail.com> wrote:
> > >http://code.google.com/p/rapidjson/
>
> > > 一直都沒能成功把一些代碼開源。這次嘗試做點盡量簡單的,工作上又可能用到的,所以就寫了一個JSON庫。
>
> > > rapidjson是一個高性能的C++ JSON
>

> > parser和generator,提供SAX/DOM風格的API,支持UTF8/16/32,可選用SSE2/SSE4.2加速,內存使用緊湊。全個庫只有--1600多行代碼的頭文件。


>
> > > 在性能方面,rapidjson受rapidxml啟發(從名字也能想到吧),支持in-situ
> > > parsing。這是指會把字符串的解碼直接寫到源字符串去。我比較了其他兩個C/C++ JSON parser,這裡只寫一點數據,有空再整理。
>
> > > 在VC2010的一個測試中,parse一個672KB的JSON文件至DOM,rapidjson 730μs,YAJL
> > > 6149μs,JsonCpp

> > 6680μs,而strlen()也需要495μs。能夠接近strlen()的速度應該算是不錯,但這和VC2010的strlen()性能較差也有關係。c--ygwin中跑gcc的strlen()只需189μs。


>
> > > 性能源於幾方面,in-situ parsing、用SSE4.2跳過whitespace,使用lookup table計算pow10(int
> > > x)等等。另外還有C++的強項,我使用template進行功能的組合,沒有虛函數的多態,也充分利用到inline的好處。
>
> > > 在VC2010中跳過1M個whitespace,strspn()要3074μs,而SSE4.2加速後只需100μs。這段代碼對很多項目都能使用。
>
> > > 另外,原本能選用C++
> > exception,後來加入setjmp/longjmp後,覺得完全沒需要使用exception,這方面也能提高少量的性能。
>

> > 預設的內存allocator是只分配不釋放的,而且parsing時特別設計過,不會產生如std::vector::push_back()時的copy及--內存浪費。每個JSON


> > > value在32-bit/64-bit系統中分別佔16及20 bytes(不含字符串)。
>
> > > 設計上提取了一些concept去組合不同功能。例如Reader會從實現了Stream
> > > concept的類讀取字符,之後parse時,把事件傳送給實現了Handler
> > > concept的類。例如PrettyWritter實現了Handler,而產生JSON文本的流,那麼把二者聯合使用:
>
> > > Reader reader;
> > > FileStream is(stdin);
>
> > > // Prepare writer and output stream.
> > > FileStream os(stdout);
> > > PrettyWriter<FileStream> writer(os);
>
> > > // JSON reader parse from the input stream and let writer generate the
> > output.
> > > if (!reader.Parse<0>(is, writer))
> > > fprintf(stderr, "\nError(%u): %s\n",
> > > (unsigned)reader.GetErrorOffset(), reader.GetParseError());
>
> > > 就能validate及"beautify" JSON 文本。
>

> > 在rapidjson中,Document是用來實現DOM風格的API。特別之處是它能遍歷自己去產生Handler的事件。所以用以下代碼可以把一個Doc--ument聯結PrettyWriter把內容寫成JSON文本的流:


>
> > > Document document;
> > > document.Parse<0>(json);
>
> > > // modify document ...
>
> > > FileStream f(stdout);
> > > PrettyWriter<FileStream> writer(f);
> > > document.Accept(writer); // Accept() traverses the DOM and
> > generates
> > > Handler events.
>
> > > 小弟第一次做開源項目,希望大家能用得著,也多給意見。
>
> > > --
> > > Milo Yip
>

> >http://www.cnblogs.com/miloyip/http://weibo.com/miloyip/http://twitte...
>
> --
> --------------------------------------------------------------------
> Best Regards,
>
> Zhangming Niu- Hide quoted text -
>
> - Show quoted text -

johnnie chan

unread,
Nov 28, 2011, 8:24:25 PM11/28/11
to TopLanguage
似乎yajl的作者对Milo的这个performance比较很不乐意......
https://github.com/lloyd/yajl_vs_rapidjson

Milo Yip

unread,
Nov 28, 2011, 9:03:13 PM11/28/11
to pon...@googlegroups.com
這個一星期前和他溝通過了。之前的問題在於例子中用fgetc()比fread()慢很多。在我的比較中,只使用了內存中的字符串去測量parsing/generation速度。我會待完成一些新功能後,發佈0.2版本時再更新性能測試。

以下是我回覆YAJL作者的信:

Today I have investigated the issue. And have found that the
inefficiency is due to fgetc() and fputc() for stream read/write, and
perftest was only testing in-memory parsing.

This is the 0.1 version I reproduced on Ubuntu 64-bit:

$ time pretty_release_x64_gmake.exe < test_file.json > /dev/null

real 0m0.180s
user 0m0.160s
sys 0m0.010s

$ time ./json_reformat < test_file.json > /dev/null

real 0m0.118s
user 0m0.100s
sys 0m0.000s

It is very similar to the statistics you have reproduced.


Without chaning the code of the parser/generator in rapidxml, I added
two stream classes which use fread()/fwrite(). And each stream
allocates 64KB buffer in pretty (since json_reformat uses 64KB buffer
for reading). Then:

$ time pretty_release_x64_gmake.exe < test_file.json > /dev/null

real 0m0.052s
user 0m0.040s
sys 0m0.000s


Another comparison with actual write:

$ time json_reformat < test_file.json > a

real 0m0.121s
user 0m0.080s
sys 0m0.020s

$ time pretty_release_x64_gmake.exe < test_file.json > a

real 0m0.070s
user 0m0.050s
sys 0m0.010s

Finally, I think in these reformatting tests, rapidjson can be further
optimized with just validating JSON string/numbers but not decoding
and re-encoding them.

2011/11/29 johnnie chan <ich...@gmail.com>:

--

rockeet febird

unread,
Nov 29, 2011, 5:36:08 AM11/29/11
to TopLanguage
精神可嘉!
我发现你的 FindMember 使用的是 sequencial find, member 少的时候无所谓, member 多的话就悲剧了,
时间复杂度是 O(n).

On Nov 19, 2:40 am, Milo Yip <milo...@gmail.com> wrote:

> http://code.google.com/p/rapidjson/
>
> 一直都沒能成功把一些代碼開源。這次嘗試做點盡量簡單的,工作上又可能用到的,所以就寫了一個JSON庫。
>
> rapidjson是一個高性能的C++ JSON
> parser和generator,提供SAX/DOM風格的API,支持UTF8/16/32,可選用SSE2/SSE4.2加速,內存使用緊湊。全個庫只有 1600多行代碼的頭文件。
>
> 在性能方面,rapidjson受rapidxml啟發(從名字也能想到吧),支持in-situ
> parsing。這是指會把字符串的解碼直接寫到源字符串去。我比較了其他兩個C/C++ JSON parser,這裡只寫一點數據,有空再整理。
>
> 在VC2010的一個測試中,parse一個672KB的JSON文件至DOM,rapidjson 730μs,YAJL
> 6149μs,JsonCpp 6680μs,而strlen()也需要495μs。能夠接近strlen()的速度應該算是不錯,但這和VC2010的strlen()性能較差也有關係。c ygwin中跑gcc的strlen()只需189μs。
>
> 性能源於幾方面,in-situ parsing、用SSE4.2跳過whitespace,使用lookup table計算pow10(int
> x)等等。另外還有C++的強項,我使用template進行功能的組合,沒有虛函數的多態,也充分利用到inline的好處。
>
> 在VC2010中跳過1M個whitespace,strspn()要3074μs,而SSE4.2加速後只需100μs。這段代碼對很多項目都能使用。
>
> 另外,原本能選用C++ exception,後來加入setjmp/longjmp後,覺得完全沒需要使用exception,這方面也能提高少量的性能。
>

> 預設的內存allocator是只分配不釋放的,而且parsing時特別設計過,不會產生如std::vector::push_back()時的copy及 內存浪費。每個JSON

Milo Yip

unread,
Nov 29, 2011, 11:17:36 PM11/29/11
to pon...@googlegroups.com
是的,打算之後加入簡單的hashing。不過這樣會改變原來的member次序。

2011/11/29 rockeet febird <roc...@gmail.com>:


> 精神可嘉!
> 我发现你的 FindMember 使用的是 sequencial find, member 少的时候无所谓, member 多的话就悲剧了,
> 时间复杂度是 O(n).

--

jiang yu

unread,
Nov 30, 2011, 1:23:56 AM11/30/11
to pon...@googlegroups.com
跟strlen保持在一个量级确实难以置信!

jiang yu

unread,
Nov 30, 2011, 1:32:42 AM11/30/11
to pon...@googlegroups.com
compile test.sln in vs2010:

1>c:\users\mos\svn\rapidjson-read-only\include\rapidjson\rapidjson.h(85):
fatal error C1083: Cannot open include file: 'allocators.h': No such
file or directory

在 2011年11月30日 下午2:23,jiang yu <yu.jia...@gmail.com> 写道:
> 跟strlen保持在一个量级确实难以置信!

rockeet febird

unread,
Nov 30, 2011, 4:58:54 AM11/30/11
to TopLanguage
可以用:
http://blog.csdn.net/whinah/article/details/6819050
http://blog.csdn.net/whinah/article/details/6876182

On Nov 30, 12:17 pm, Milo Yip <milo...@gmail.com> wrote:
> 是的,打算之後加入簡單的hashing。不過這樣會改變原來的member次序。
>

> 2011/11/29 rockeet febird <rock...@gmail.com>:

Milo Yip

unread,
Nov 30, 2011, 9:19:21 AM11/30/11
to pon...@googlegroups.com
昨晚commit漏了文件,已上傳了。

2011/11/30 jiang yu <yu.jia...@gmail.com>:

--

Reply all
Reply to author
Forward
0 new messages