删除 std::unordered_map 不会将内存释放回操作系统 [duplicate]

Deleting std::unordered_map does not release memory back to the OS [duplicate]

提问人:Santiago 提问时间:7/27/2023 更新时间:7/27/2023 访问量:65

问:

我有如下场景,在启动我的应用程序时,我订阅了一个中间件并下载了最新的状态(快照),我需要做一些过滤逻辑,然后处理快照。为此,我将初始快照放在 .在那之后,我不再需要地图,所以我希望它的内存被释放回操作系统。未序列化的快照记录占用大量内存,最高可达 15GB。因此,释放这种记忆非常重要。这是我拥有的代码。std::unordered_map

class Consumer
{
public:
   Consumer(Processor& p)
  : m_processor(p)
  , m_snapshot(false)
  , m_sub([this](const auto& msg) {
          if (m_snapshot)
             addToCache(msg);
          else
             m_processor.process(Order(msg));
          },
          [this](const auto& state) {
          if (state == State::BEGIN)
             m_snapshot = true;
          else if (state == State::END)
             m_snapshot = false;
             playCache();
          })
{
}

private:
   void addToCache(const Input& input)
   {
      // if logic
      m_cache[input.header.key()] = Order(input);
   }

   void playCache()
   {
       for (auto& [_, order] : m_cache)
          m_processor(std::move(order));

       m_cache.clear();
   }

private:
   Processor m_processor;
   bool m_snapshot;
   Sub m_sub;
   std::unordered_map<std::string, Order> m_cache;
};

这显然不会将内存释放回操作系统(签入我的进程,它仍然使用相同数量的内存)。htop

“m_processor”“使用”消息,仅在字符串中存储序列化版本。Order

我很确定内存没有被释放,它来自这张地图,因为我做了以下测试:

  • 无需进行任何过滤(根本不添加)并简单地处理所有消息(即使它们更多)可以显着降低 5GB 左右的内存消耗,而 15GB 的缓存进行过滤然后处理。m_cache
  • 我很确定上游没有内存泄漏。我尝试注释掉添加到地图和处理的部分。又名,仍然获取快照,但将其扔掉,我再次获得更少的内存使用量。m_sub

我知道这并不意味着释放内存,因此正如其他帖子中建议的那样,我尝试了以下操作:.clear()

  • 进行交换,即:playCache
   void playCache()
   {
       for (auto& [_, order] : m_cache)
          m_processor(std::move(order));

       m_cache.clear();
       std::unordered_map<std::string, Order> empty;
       std::swap(m_cache, empty);
   }

相同的结果是,内存不会释放回操作系统。

  • 完成后进行和调用重置:m_cachestd::unique_ptr
   void playCache()
   {
       for (auto& [_, order] : *m_cache)
          m_processor(std::move(order));

       m_cache->clear();
       m_cache.reset();
   }

结果还是一样。

我错过了什么吗?为什么内存没有释放回操作系统?

如果它有帮助,数据类型很简单:

struct Order {
    Order() = default;
    Order(const Input& i)
    : header_(i.header())
    , body_(deserializeProto(i.body())
{
}
   protobuf::Header header_;
   protobuf::Body body_;
};

提前致谢。

C++ 内存管理 标准分配

评论

2赞 Yksisarvinen 7/27/2023
delete不需要将内存返回到操作系统,并且很少这样做。获取内存并将其释放回操作系统是一项成本高昂的操作,因此程序可以保留内存,直到操作系统请求返回内存或程序结束。
1赞 Yksisarvinen 7/27/2023
这回答了你的问题吗?强制将内存释放到操作系统(剧透警告:答案说你不能)。
1赞 Ted Lyngmo 7/27/2023
@Santiago 为什么会导致泄漏?
1赞 Ted Lyngmo 7/27/2023
泄漏从何而来?
2赞 Daniel Langr 7/27/2023
@JakobStark操作系统无法从程序请求返回分配的虚拟内存。但它可以请求从物理内存中取消映射,并将释放的物理内存用于其他程序。

答: 暂无答案