處理 JSON 數據的C++開發包:JsonCpp使用優化

jopen 11年前發布 | 17K 次閱讀 JSON開發包 JSONCPP

JsonCpp 是一個 C++ 用來處理 JSON 數據的開發包。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>

usingnamespacestd;

int64_t getCurrentTime() { structtimeval tval; gettimeofday(&tval, NULL); return(tval.tv_sec * 1000000LL + tval.tv_usec); }

char* str ="abcdefghijklmnopqrstuvwxyz";

voidtest1() { intdoc_count = 40; intouter_field_count = 80;

Json::Value common_info;

int64_t start_time = getCurrentTime();

for(size_ti=0; i<doc_count; ++i)
{
    Json::Value auc_info;
    for(size_tj=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;

}

voidtest2() { intdoc_count = 40; intouter_field_count = 80;

Json::Value common_info;

int64_t start_time = getCurrentTime();

Json::Value auc_info;

for(size_ti=0; i<doc_count; ++i)
{
    for(size_tj=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;

}

voidtest3() { intdoc_count = 40; intouter_field_count = 80;

Json::Value common_info;

int64_t start_time = getCurrentTime();

Json::Value auc_info;

for(size_ti=0; i<doc_count; ++i)
{
    for(size_tj=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;

}

intmain(intargc,constchar*argv[]) { test1(); test2(); test3();

return0;

}</strong></pre>

編譯優化

默認情況下,JsonCpp編譯時并沒有帶優化參數,自己可以加上優化參數。Linux環境下在下面這段代碼中的CCFLAGS加入”O2″。

1

2

3

4
</td>

elifplatform.startswith('linux-gcc'):

    env.Tool('default')

    env.Append( LIBS=['pthread'], CCFLAGS="-Wall -fPIC O2")

    env['SHARED_LIB_ENABLED']=True
</div> </td> </tr> </tbody> </table> </div> </div>

可以看到使用O2優化比默認編譯的版本性能提升一倍多。

  • 1

    2

    3

    4

    5

    6

    7
    </td>

    append time: 4946

    opt append time: 3326

    StaticString time: 2750

     

    append time: 1825

    opt append time: 1082

    StaticString time: 845
    </div> </td> </tr> </tbody> </table> </div> </div>

    使用方法上的優化

    測試代碼中第三種方法比第一種方法效率提升了一倍多。第三種方法之所以效率更高,有兩個原因。

    1、首先是在循環中一直復用auc_info對象。第一個循環就能將auc_info的長度初始化為doc_count。通過下標的訪問方法,一直復用數組中的元素。

    2、如果key和value內存不會被釋放,那么使用StaticString效率會更高,省去了構造CZString時拷貝的開銷。

    代碼優化

    因為在JsonCpp中一切都是Value,所以會有大量的隱性類型轉換,要構造大量的Value對象。為了提高性能,可以在實現繞過這個機制,犧牲一致性。

    因為Value最常用的類型是字符串,因此給Value增加一個setValue函數。

    1

    2

    3

    4

    5

    6

    7
    </td>

    void

    Value::setValue(constStaticString& value )

    {

       type_ = stringValue;

       allocated_ =false;

       value_.string_ =const_cast<char*>( value.c_str() );

    }
    </div> </td> </tr> </tbody> </table> </div> </div>

    再測試一下性能,可以發現性能較第三種方法還有提升。

  • 1

    2

    3

    4
    </td>

    append time: 1849

    opt append time: 1067

    StaticString time: 843

    setValue time: 570
    </div> </td> </tr> </tbody> </table> </div> </div>

    最后還有一個辦法就是靜態鏈接。JsonCpp庫本身非常小,將其靜態鏈接能稍微提升一點性能。下面是靜態鏈接時基準測試程序的耗時情況。

    1

    2

    3

    4
    </td>

    append time: 1682

    opt append time: 1011

    StaticString time: 801

    setValue time: 541
    </div> </td> </tr> </tbody> </table>

    原文地址:http://www.searchtb.com/2012/11/jsoncpp-optimization.html

     本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
     轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
     本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
  • sesese色