1

我正在使用nlohmann库来解析JSON代码。我们有两个问题:
1- 为什么nlohmann使用巨大的内存来解析数据
2- 在本地函数中调用解析器后,就像下面的代码一样,它不会释放内存。我的JSON数据大小约为 8MB,解析器使用超过50MB进行解析。我解析了这个JSON数据10次,内存使用量上升到600MB,函数完成后内存没有释放。

#include "nlohmann/json.hpp"

    #define REPEAT 10

        void GenerateNlohmann() {
          std::string filePath{FILE_ADDRESS};
          std::ifstream iFile(filePath.c_str(), std::ios::in);
          std::string data{};
          if (iFile.is_open()) {
            data = std::string((std::istreambuf_iterator<char>(iFile)),
                               std::istreambuf_iterator<char>()); // About 8MB size
            iFile.close();
          }
          if (!data.empty()) {
            nlohmann::json json = nlohmann::json::parse(data); // Use memory about 50MB
            std::vector<nlohmann::json> jsons{};
            for (int i = 0; i < REPEAT; ++i) {
              nlohmann::json j = nlohmann::json::parse(data);
              jsons.emplace_back(j);
            }
            while (!jsons.empty()) {
              jsons.pop_back();
            }
          }
        }

            int main() {
              GenerateNlohmann();

        // Now memory usage is about 600MB
              std::cout << "Input a numberto exit" << std::endl;
              int i;
              std::cin >> i;

              return 0;
            }
4

1 回答 1

0

我在 ubuntu 中复制成功。我的 json 数据大小约为 1.4 KB,但我多次解析了这个 json 数据。这是我的测试结果:

运行前:

KiB Mem :  8167476 total,  5461204 free,   284120 used,  2422152 buff/cache

1000 times:
KiB Mem :  8167476 total,  5456600 free,   288724 used,  2422152 buff/cache

10000 times:
KiB Mem :  8167476 total,  5405916 free,   339376 used,  2422184 buff/cache

100000 times:
KiB Mem :  8167476 total,  4893176 free,   852104 used,  2422196 buff/cache

After input the int (After run)
KiB Mem :  8167476 total,  5462208 free,   283116 used,  2422152 buff/cache

确实存在问题,但这是分配器(在我的情况下可能是glibc)的优化,与库无关。

如果我在我的代码中添加malloc_trim(0) :

while (!jsons.empty()) {
      jsons.pop_back();
    }

+   malloc_trim(0);
  }

我会发现一切都会好起来的。我认为在 Windows 中我们无法重现,因为我们使用的不是glibc

其他测试:我用glibc编写了其他程序来 malloc 很多小内存,问题仍然存在。我的程序与库无关,它只是 malloc 并释放了很多小内存。

无论如何,这个问题与图书馆无关。如果我们将malloc_trim(0)添加到库中,在解析过程中会出现很多调用,这会降低性能。所以更好的解决方案是在代码中添加malloc_trim(0)

于 2020-02-10T07:27:49.353 回答