You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ PMR多态内存资源选型:支持按需释放闲置内存的方案问询

符合需求的PMR内存资源实现方案

标准库自带的PMR内存资源确实没有主动返还闲置内存的能力,你可以通过自定义std::pmr::memory_resource子类实现需求,既保留池化内存的局部性优化收益,又能在低峰期释放多余内存降低占用。

核心实现逻辑

  • 内部维护分大小类的空闲内存池,对每个大小类的空闲块设置最大缓存阈值,超过阈值的空闲块在归还时直接调用上游的deallocate释放回上游
  • 额外提供手动trim()接口,调用时释放所有超过最小保留量的空闲内存,你可以在守护进程的低峰调度逻辑里定时/按需调用该接口,效果完全等价于按需调用malloc_trim
  • 线程安全版本可在内部加读写锁实现,性能和标准的synchronized_pool_resource接近,仅多一次阈值判断的开销,对整体性能影响极小

极简示例实现

#include <memory_resource>
#include <mutex>
#include <vector>
#include <unordered_map>

class trimable_pool_resource : public std::pmr::memory_resource {
private:
    std::pmr::memory_resource* upstream;
    std::mutex mtx;
    // 每个大小类最多缓存的块数,可根据业务调整
    static constexpr size_t max_cached_blocks_per_size = 8;
    // 大小类 -> 空闲块列表
    std::unordered_map<size_t, std::vector<void*>> free_lists;

protected:
    void* do_allocate(size_t bytes, size_t alignment) override {
        std::lock_guard lk(mtx);
        // 优先从空闲列表取已缓存的块
        if (auto it = free_lists.find(bytes); it != free_lists.end() && !it->second.empty()) {
            void* ptr = it->second.back();
            it->second.pop_back();
            return ptr;
        }
        // 无可用缓存则从上游分配
        return upstream->allocate(bytes, alignment);
    }

    void do_deallocate(void* p, size_t bytes, size_t alignment) override {
        std::lock_guard lk(mtx);
        auto& list = free_lists[bytes];
        if (list.size() < max_cached_blocks_per_size) {
            // 未达缓存阈值则留存
            list.push_back(p);
            return;
        }
        // 超过阈值直接返还上游
        upstream->deallocate(p, bytes, alignment);
    }

    bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
        return this == &other;
    }

public:
    explicit trimable_pool_resource(std::pmr::memory_resource* upstream = std::pmr::get_default_resource())
        : upstream(upstream) {}

    // 手动裁剪接口,低负载时调用即可释放多余闲置内存
    void trim() {
        std::lock_guard lk(mtx);
        for (auto& [size, list] : free_lists) {
            // 每个大小类仅保留2块最小缓存,其余全部释放,阈值可自行调整
            while (list.size() > 2) {
                void* p = list.back();
                list.pop_back();
                upstream->deallocate(p, size, alignof(std::max_align_t));
            }
        }
    }

    ~trimable_pool_resource() override {
        // 析构时释放所有缓存的内存
        trim();
        for (auto& [size, list] : free_lists) {
            for (void* p : list) {
                upstream->deallocate(p, size, alignof(std::max_align_t));
            }
        }
    }
};

使用说明

  • 上述实现可以直接替换你当前使用的synchronized_pool_resource/unsynchronized_pool_resource,内存局部性优化效果和标准池化资源一致
  • 你可以在守护进程的低负载检测逻辑中直接调用trim()方法,即可立刻释放多余的闲置内存回上游,完全符合你按需降低内存占用的需求
  • 可通过修改max_cached_blocks_per_size和trim方法中的保留阈值,平衡内存占用和分配性能
  • 如果仅在单线程场景使用,可以去掉内部的mutex锁,性能和unsynchronized_pool_resource完全一致

内容的提问来源于stack exchange,提问作者戴均維

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 21:39:03