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());
}
这种方式既能节省内存,也能提高效率。
参考资料: