欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

rapidjson使用小结

程序员文章站 2024-02-02 21:39:46
...

使用Document时内存问题


rapidjson的使用简介可以参考rapidjson使用简介

使用rapidjson解析时,简单的使用方法是使用Document对象的parse方法直接搞定,如下:

const char *json = "{\"index\": 5}";
Document d;
d.Parse(json);

//直接使用 int i = d["index"]; 获取值

这是不会有什么问题的,但是如下代码片段:

// 伪代码
Document d;
string json;

while(true)
{
	recv json;//一直从网络接收json数据,保存到json
	d.parse(json);
	// ...
	// 使用完毕
}

当数据量很大时,会占用很大的内存,且内存会持续升高,可以使用如下代码测试:

#include <iostream>
#include <thread>
#include "rapidjson/document.h"

using namespace std;
using namespace rapidjson;

int main()
{
    string json = "\"SellPrice\":[77.3,77.4,77.44,77.45,77.46,77.47,77.48,77.49,77.5,77.52],\"SellVolume\":[464,1000,1400,1800,200,3500,200,5564,900,2549],"
				   "\"BuyPrice\":[77.29,77.23,77.18,77.17,77.14,77.01,77.0,76.99,76.98,76.97],\"BuyVolume\":[5438,500,200,2068,1644,2300,3831,7152,895,200],"
				   "\"TotalVolume\":8201363,\"Time\":\"131423\",\"BuyLevelQueue\":[850,2116,2472,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"
				   "\"SellLevelQueue\":[464,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"TotalAmount\":628685368.05,"
				   "\"TotalNo\":13697,\"IOPV\":0.0}";

    Document d;

    while(true)
    {
        d.Parse(json.c_str());
        std::this_thread::sleep_for(std::chrono::microseconds(10));// 防止cpu占用过高
        // 定期输出memory使用信息
        // process_mem_usage(vm, rss);
        // 也可以通过top等命令查看进程使用内存情况
    }
}

上述代码执行后,内存呈急骤上升状态,很快达到1G以上。根据网上资料,调用document的parse方法解析json字符串,内部的stack会扩容两次,这种方法最浪费内存。

使用一个新的Document对象,Swap原来的d,内存使用得到缓解,但仍占用较多的内存。

此时,作一个小小的改动,把Document d;一行放在循环体内,内存使用就正常了。但此时每次要 malloc() 两块内存,效率较低。

可以使用缓存模式,以尽可能达到0内存分配:

typedef GenericDocument<UTF8<>, MemoryPoolAllocator<>, MemoryPoolAllocator<> > DocumentType;
char valueBuffer[8192];
char parseBuffer[8192];

while (true)
{
    MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer));
    MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer));
    DocumentType dt(&valueAllocator, sizeof(parseBuffer), &parseAllocator);
    dt.Parse(json.c_str());
}

这种方式既能节省内存,也能提高效率。

参考资料:

Document parse的性能非常慢
Memory leak - Parse