我有以下场景,当启动我的应用程序时,我订阅中间件并下载最新状态(快照),我需要做一些过滤逻辑,然后处理快照。为此,我将初始快照放在
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_;
};
提前致谢。