一直都沒能成功把一些代碼開源。這次嘗試做點盡量簡單的,工作上又可能用到的,所以就寫了一個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/
http://code.google.com/p/rapidjson/wiki/Performance
至於github,鑑於本人不懂Git,可能留待他日再作轉移。
我有空會繼續寫使用手冊、內存比較、設計等文檔。
希望各位多給意見。
配置文件的特点不外乎这几点,轻便简单易读,能跨平台跨语言,支持unicode编码。json是唯一完美支持这几个特性的。
----------------------------------------------------------------------------------
Yours Sincerely
Kun
2011/11/26 翁翊成 <wen...@gmail.com>:
还是用小型的函数式脚本语言做配置更能满足各种复杂的要求。
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文本的流:
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 -
以下是我回覆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>:
--
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
2011/11/29 rockeet febird <roc...@gmail.com>:
> 精神可嘉!
> 我发现你的 FindMember 使用的是 sequencial find, member 少的时候无所谓, member 多的话就悲剧了,
> 时间复杂度是 O(n).
--
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保持在一个量级确实难以置信!
On Nov 30, 12:17 pm, Milo Yip <milo...@gmail.com> wrote:
> 是的,打算之後加入簡單的hashing。不過這樣會改變原來的member次序。
>
> 2011/11/29 rockeet febird <rock...@gmail.com>: