你好!
我有一个关于 jsoncpp 内存的问题。我必须使用 jsoncpp 在 c++ 中加载大型 JSon 文件(55 MB)。我注意到我的程序使用了大量的内存。我尝试了一些方法,只是打开、解析并关闭 JSON 文件。关闭文件后,内存使用量根本没有减少。
我也尝试使用RapidJson,返回后释放了很多内存。
我使用的是Linux
我尝试了这段代码,它在 Jsoncpp 解析之前和之后打印 /proc/PID/statm 中的 statm 文件。 它打印解析函数之前、期间和之后的内存。
#include <iostream>
#include <json/json.h>
#include <fstream>
#include <unistd.h>
#include <iostream>
#include <json/json.h>
#include <fstream>
#include <unistd.h>
#include <rapidjson/istreamwrapper.h>
#include <rapidjson/document.h>
void printmem()
{
char tmp[128];
std::string t;
sprintf(tmp, "/proc/%d/statm", getpid());
std::ifstream ifs(tmp);
std::getline(ifs, t);
std::cout << t <<"\n";
ifs.close();
}
void jsoncpp()
{
std::ifstream ifs("../../../AlloDB/db.json");
Json::CharReaderBuilder builder;
Json::Value value;
JSONCPP_STRING errs;
Json::parseFromStream(builder, ifs, &value, NULL);
ifs.close();
printmem();
}
void rapid_json()
{
using namespace rapidjson;
std::ifstream ifs("../../../AlloDB/db.json");
std::string t;
IStreamWrapper isw(ifs);
Document d;
d.ParseStream(isw);
printmem();
}
int main(int argc, char** argv)
{
printmem();
//jsoncpp();
rapid_json();
printmem();
}
结果是: 对于jsoncpp
2552 629 516 51 0 188 0
107744 106364 1052 51 0 105380 0
107744 106364 1052 51 0 105380 0
因此在解析之前,使用的总内存为 2552*4096 +/-= 10 MiB。函数期间和之后的内存使用量完全相同 107744*4096 +/-= 420 MiB。
对于RapidJson:
2552 642 530 51 0 188 0
24275 22871 1056 51 0 21911 0
4140 2780 1056 51 0 1776 0
RapidJson 释放了大量内存,但没有完全释放。
Jsoncpp 在返回 jsoncpp() 后应该释放他的内存,不是吗?我用这个程序(用jsoncpp)尝试了Valgrind,没有内存泄漏。
==133628== Memcheck, a memory error detector
==133628== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==133628== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==133628== Command: bin/Debug/db
==133628==
50448 39807 1539 498 0 47403 0
649572 639457 1671 498 0 646527 0
440676 431819 1671 498 0 437631 0
==133628==
==133628== HEAP SUMMARY:
==133628== in use at exit: 0 bytes in 0 blocks
==133628== total heap usage: 5,917,609 allocs, 5,917,609 frees, 601,544,185 bytes allocated
==133628==
==133628== All heap blocks were freed -- no leaks are possible
==133628==
==133628== For lists of detected and suppressed errors, rerun with: -s
==133628== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
为什么 jsoncpp 在返回 jsoncpp() 函数时不释放内存? 解析后我不需要访问数据,热清理它?
谢谢
从 github copilot 得到这个回复:
代码:
#include <fstream>
#include "json/json.h"
#include <iostream>
#include <unistd.h>
#include <memory>
#include <vector>
using namespace std;
void qq()
{
int z[1024*1024];
std::string path = "list.json";
std::ifstream ifs(path);
std::unique_ptr<Json::Value> root = std::make_unique<Json::Value>();
Json::Reader reader;
reader.parse(ifs, *root);
if (ifs.is_open())
ifs.close();
sleep(30);
}
int main()
{
qq();
cout << "loop done" << endl;
sleep(30);
cout << "exit" << endl;
return 0;
}
问: 退出 qq() 后,我没有看到 VmRSS 有任何减少
答: 您观察到的 VmRSS 在退出 qq() 后没有减少的行为可能归因于以下几个因素:
栈内存(int z[1024*1024];):栈上为数组z分配的内存确实在qq()退出时被释放。然而,这种类型的内存释放并不一定会导致操作系统看到的 VmRSS 立即减少。堆栈空间被回收,但由于操作系统管理内存的方式,VmRSS 报告的进程内存占用可能不会缩小。线程的堆栈可能不会立即收缩,或者可能会被同一线程重用。
堆内存(std::unique_ptrJson::Value root):在堆上为 root 分配的内存由 std::unique_ptr 管理,当 root 超出范围时(当 qq( 时发生),它会自动释放内存)退出)。然而,与堆栈内存类似,将堆内存释放回操作系统可能不会立即反映 VmRSS 的减少。 C++ 运行时可能会保留分配的内存以供将来分配(以避免频繁分配和释放的成本)。
内存碎片和管理:C++ 运行时和操作系统采用的内存碎片和内存管理策略会影响内存返回系统的方式和时间。运行时可能会保留内存以供将来在进程内分配。
操作系统缓存和内存管理:操作系统可能不会立即回收或显示 VmRSS 的减少,因为它可能正在缓存内存页面或在同一进程中将它们用于其他目的。操作系统具有复杂的内存管理算法,这些算法并不总是立即反映进程内存使用情况的变化。
文件流和其他资源:打开文件流和其他资源(例如在 std::ifstream ifs(path); 中)会分配不直接可见的堆或堆栈内存。这些资源在您的代码中已正确关闭和清理,但它们的内存占用也可能以不立即明显的方式影响 VmRSS。
总而言之,退出 qq() 后 VmRSS 没有明显下降可能是由于运行时和操作系统级别的内存管理的潜在复杂性所致。请务必注意,VmRSS 是一个粗略指标,可能不会立即或小幅增量地反映内存使用情况的变化。