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

问题描述 投票:0回答:0

我有以下场景,当启动我的应用程序时,我订阅中间件并下载最新状态(快照),我需要做一些过滤逻辑,然后处理快照。为此,我将初始快照放在

std::unordered_map
中。之后我不再需要该地图,因此我希望将其内存释放回操作系统。未序列化的快照记录占用大量内存,最多 15GB。因此,释放该内存非常重要。这是我的代码。

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
消息,仅在字符串中存储序列化版本。

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

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

我知道

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

  • 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_cache
    设为
    std::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++ memory-management std allocation
© www.soinside.com 2019 - 2024. All rights reserved.