JsonCpp使用优化
最近一个项目在使用JsonCpp,JsonCpp简洁易用的接口让人印象深刻。但是在实际使用过程中,我发现JsonCpp的性能却不尽如人意,所以想着方法优化下性能。
代码理解
1、JsonCpp中一切都是Value,Value用union指向自己保存的数据。Value的类型分为两种,一种是容器类型,比如arrayValue和objectValue。二者都是用map保存数据,只是arrayValue的key为数字而已。另外一种是基本类型,比如字符串,整型数字等等。
2、解释JSON数据时,JsonCpp在operator[]函数开销比较大。JsonCpp内部使用std::map,查找性能方便,map不如hash_map,但是将map替换成hash_map有一定的困难,因为map的key为CZString,而这个类又是Value的内部类,导致不能定义hash_map需要的hash结构体。
本来想尝试下internal map,结果开启JSON_VALUE_USE_INTERNAL_MAP这个宏之后,根本通不过编译,因为value.h中有一处uion声明里面居然放的是结构体,不知道什么编译器支持这种语法。
基准测试程序
#include <iostream> #include <string> #include <sys/time.h> #include <time.h> #include <json/json.h> using namespace std; int64_t getCurrentTime() { struct timeval tval; gettimeofday(&tval, NULL); return (tval.tv_sec * 1000000LL + tval.tv_usec); } char * str = "abcdefghijklmnopqrstuvwxyz"; void test1() { int doc_count = 40; int outer_field_count = 80; Json::Value common_info; int64_t start_time = getCurrentTime(); for(size_t i=0; i<doc_count; ++i) { Json::Value auc_info; for( size_t j=0 ; j<outer_field_count; ++j ) { auc_info.append(str); } common_info.append(auc_info); } int64_t end_time = getCurrentTime(); cout << "append time: " << end_time - start_time << endl; } void test2() { int doc_count = 40; int outer_field_count = 80; Json::Value common_info; int64_t start_time = getCurrentTime(); Json::Value auc_info; for(size_t i=0; i<doc_count; ++i) { for( size_t j=0 ; j<outer_field_count; ++j ) { auc_info[j] = str; } common_info.append(auc_info); } int64_t end_time = getCurrentTime(); cout << "opt append time: " << end_time - start_time << endl; } void test3() { int doc_count = 40; int outer_field_count = 80; Json::Value common_info; int64_t start_time = getCurrentTime(); Json::Value auc_info; for(size_t i=0; i<doc_count; ++i) { for( size_t j=0 ; j<outer_field_count; ++j ) { auc_info[j] = Json::StaticString(str); } common_info.append(auc_info); } int64_t end_time = getCurrentTime(); cout << "StaticString time: " << end_time - start_time << endl; } int main(int argc, const char *argv[]) { test1(); test2(); test3(); return 0; }
编译优化
默认情况下,JsonCpp编译时并没有带优化参数,自己可以加上优化参数。Linux环境下在下面这段代码中的CCFLAGS加入”O2″。
elif platform.startswith(\'linux-gcc\'): env.Tool( \'default\' ) env.Append( LIBS = [\'pthread\'], CCFLAGS = "-Wall -fPIC O2" ) env[\'SHARED_LIB_ENABLED\'] = True
可以看到使用O2优化比默认编译的版本性能提升一倍多。
append time: 4946 opt append time: 3326 StaticString time: 2750 append time: 1825 opt append time: 1082 StaticString time: 845
使用方法上的优化
测试代码中第三种方法比第一种方法效率提升了一倍多。第三种方法之所以效率更高,有两个原因。
1、首先是在循环中一直复用auc_info对象。第一个循环就能将auc_info的长度初始化为doc_count。通过下标的访问方法,一直复用数组中的元素。
2、如果key和value内存不会被释放,那么使用StaticString效率会更高,省去了构造CZString时拷贝的开销。
代码优化
因为在JsonCpp中一切都是Value,所以会有大量的隐性类型转换,要构造大量的Value对象。为了提高性能,可以在实现绕过这个机制,牺牲一致性。
因为Value最常用的类型是字符串,因此给Value增加一个setValue函数。
void Value::setValue( const StaticString& value ) { type_ = stringValue; allocated_ = false; value_.string_ = const_cast<char *>( value.c_str() ); }
再测试一下性能,可以发现性能较第三种方法还有提升。
append time: 1849 opt append time: 1067 StaticString time: 843 setValue time: 570
最后还有一个办法就是静态链接。JsonCpp库本身非常小,将其静态链接能稍微提升一点性能。下面是静态链接时基准测试程序的耗时情况。
append time: 1682 opt append time: 1011 StaticString time: 801 setValue time: 541
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:恨少 来源: 搜索技术博客-淘宝
- 标签: JsonCpp
- 发布时间:2012-11-02 13:04:03
- [65] Oracle MTS模式下 进程地址与会话信
- [64] Go Reflect 性能
- [64] 如何拿下简短的域名
- [59] IOS安全–浅谈关于IOS加固的几种方法
- [58] 【社会化设计】自我(self)部分――欢迎区
- [58] 图书馆的世界纪录
- [56] android 开发入门
- [53] 视觉调整-设计师 vs. 逻辑
- [46] 读书笔记-壹百度:百度十年千倍的29条法则
- [45] 界面设计速成