synchronized_pool_resource 是如何工作的?

How the synchronized_pool_resource actually works?

我正在研究C++17中的多态内存分配。 我修改了一个使用 monotonic_buffer_resource 进行矢量分配的示例,以使用 synchronized_pool_resource。 我检测到一个奇怪的行为。具体来说,有很多内存分配,只是为了向量中的两次加法。我没有 运行 基准测试,但我认为这对性能来说是一个巨大的损失

程序是使用O2编译的 g++ -std=c++17 -O2 -Wall -pedantic

下面是代码

class debug_resource : public std::pmr::memory_resource {

public:
    explicit debug_resource(std::string name,
        std::pmr::memory_resource* up = std::pmr::get_default_resource())
        : _name{ std::move(name) }, _upstream{ up }
    { }

    void* do_allocate(size_t bytes, size_t alignment) override {
        std::cout << _name << " do_allocate(): " << bytes << '\n';
        void* ret = _upstream->allocate(bytes, alignment);
        return ret;
    }
    void do_deallocate(void* ptr, size_t bytes, size_t alignment) override {
        std::cout << _name << " do_deallocate(): " << bytes << '\n';
        _upstream->deallocate(ptr, bytes, alignment);
    }
    bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
        return this == &other;
    }

private:
    std::string _name;
    std::pmr::memory_resource* _upstream;
};
int main()
{
  
    debug_resource default_dbg{ "default" };
    std::pmr::synchronized_pool_resource pool(&default_dbg);
  //  debug_resource dbg{ "pool", &pool };
    std::pmr::vector<std::string> strings{ &pool };

   strings.emplace_back("Hello Short String");
   strings.emplace_back("Hello Short String 2");
}

控制台输出如下

默认do_allocate(): 32
默认 do_allocate(): 528
默认 do_allocate(): 32
默认 do_allocate(): 528
默认 do_allocate(): 1000
默认 do_allocate(): 192
默认 do_allocate(): 968
默认 do_allocate(): 192

默认do_deallocate(): 528
默认 do_deallocate(): 32
默认 do_deallocate(): 1000
默认 do_deallocate(): 192
默认 do_deallocate(): 968
默认 do_deallocate(): 192
默认 do_deallocate(): 528
默认 do_deallocate(): 32

答案在函数描述中:https://en.cppreference.com/w/cpp/memory/synchronized_pool_resource

It consists of a collection of pools that serves request for different block sizes. Each pool manages a collection of chunks that are then divided into blocks of uniform size.

Calls to do_allocate are dispatched to the pool serving the smallest blocks accommodating the requested size.

Exhausting memory in the pool causes the next allocation request for that pool to allocate an additional chunk of memory from the upstream allocator to replenish the pool. The chunk size obtained increases geometrically.

The largest block size and maximum chunk size may be tuned by passing a std::pmr::pool_options struct to its constructor.

所以一个池实际上是内存块的集合。并在必要时增加此集合。因此多次分配。

要减少分配的数量,您可以尝试使用 std::pmr::pool_options