zoukankan      html  css  js  c++  java
  • JsonCpp使用优化

    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声明里面居然放的是结构体,不知道什么编译器支持这种语法。

    基准测试程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    #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″。

    1
    2
    3
    4
    elif platform.startswith('linux-gcc'):
        env.Tool( 'default' )
        env.Append( LIBS = ['pthread'], CCFLAGS = "-Wall -fPIC O2" )
        env['SHARED_LIB_ENABLED'] = True

    可以看到使用O2优化比默认编译的版本性能提升一倍多。

    1
    2
    3
    4
    5
    6
    7
    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函数。

    1
    2
    3
    4
    5
    6
    7
    void
    Value::setValue( const StaticString& value )
    {
       type_ = stringValue;
       allocated_ = false;
       value_.string_ = const_cast<char *>( value.c_str() );
    }

    再测试一下性能,可以发现性能较第三种方法还有提升。

    1
    2
    3
    4
    append time: 1849
    opt append time: 1067
    StaticString time: 843
    setValue time: 570

    最后还有一个办法就是静态链接。JsonCpp库本身非常小,将其静态链接能稍微提升一点性能。下面是静态链接时基准测试程序的耗时情况。

    1
    2
    3
    4
    append time: 1682
    opt append time: 1011
    StaticString time: 801
    setValue time: 541
  • 相关阅读:
    关于二分操作的基本应用
    东北育才 d1t4 漂流
    东北育才 d1t1 优雅的序列
    从零开始的图的存储方法
    从零理解的KMP算法
    openjudge T017 黑社会团伙 (并查集)
    东北育才 day6
    poj3071 Football
    noip2015 跳石头
    noip2015 信息传递
  • 原文地址:https://www.cnblogs.com/lexus/p/2750760.html
Copyright © 2011-2022 走看看