c++ - 使用 boost.pool 而不是 'new' 作为对象容器

标签 c++ boost pool boost-pool

在我正在处理的代码库中,它目前有经常执行此操作的代码:

// In the header:
class Label
{
public:
    void ParseText();

private:
    Letter* m_myArray;
};

// In the CPP:
void ParseText()
{
    delete[] m_myArray;
    m_myArray = new Letter[string_length];
    // ......
}

基本上每次标签中的字符串发生变化时,我们都会删除旧的字母对象集并重新创建它们。这些字母对象有些轻量级,但由于这种情况经常发生,我不能简单地使用 std::vector<Letter>因为每个push_back()会产生一个拷贝。我也想避免复制。

在这里使用 boost 池会有帮助吗?我可以想象这样做(这是伪代码,因为我还不确定如何使用 boost 池):

// In the header:
class Label
{
public:
    void ParseText();

private:
    std::vector<Letter*> m_myArray;
    boost::object_pool m_pool;
};

// In the CPP:
void ParseText()
{
    // Loop through each element in m_myArray and call pool::free
    m_myArray.clear();

    // Loop each letter and create a new Letter object in the container
    for( ... ) {
        m_myArray.push_back(m_pool.malloc()); // Not sure how to handle constructor params
    }

    // ......
}

这将避免复制并避免如此频繁地进行分配。但是,我降低了代码的可维护性,因为在 vector 中添加/删除项目涉及太多样板。

我考虑过将 boost::ptr_vector 与自定义删除器一起使用,但不确定这是否有帮助。它有助于清理,但我仍然必须调用 pool::malloc()每次我做一个 push_back。

将自定义分配器与 std::vector 一起使用似乎也没有意义,因为它无论如何都是预先分配的,并且不会缩小大小。

谁能帮我找出解决这个问题的“最佳”解决方案?

最佳答案

我认为内存池在某些情况下会有所不同。自 boost::object_pool<>没有提供分配对象数组的方法,所以我会使用 boost::pool<>这实际上是boost::object_pool<>的底层内存池.

#include <cstdio>
#include <ctime>
#include "boost/pool/pool.hpp"

struct Letter{
    float a, b, c;
    int *p;
};

class Label
{
public:
    Label() : m_myArray(NULL), string_length(1), last_size(0){}

    void set_size(size_t n)
    {
        last_size = string_length; // use last_size to store the number of last allocation, just for test.
        string_length = n;
    }
    void ParseText()
    {
        delete[] m_myArray;
        m_myArray = new Letter[string_length];
    }

    void ParseText_pool();

private:
    Letter* m_myArray;
    size_t string_length;
    size_t last_size; //boost::pool<>::ordered_free need the size
};

boost::pool<> p(sizeof(Letter));

void Label::ParseText_pool()
{
    if(m_myArray)
        p.ordered_free(m_myArray, last_size); // ordered_free need the right size
    m_myArray = (Letter*)p.ordered_malloc(string_length); // if you need call the ctor, use placement new.
}

int main()
{
    Label l;

    float startTime = (float)clock()/CLOCKS_PER_SEC;

    for(int i = 1; i < 1000000; ++i)
    {
        l.set_size(i%100 + 1);
        l.ParseText();
    }

    float endTime = (float)clock()/CLOCKS_PER_SEC;

    printf("without pool, time: %f\n", endTime - startTime);

    Label l2;
    startTime = (float)clock()/CLOCKS_PER_SEC;

    for(int i = 1; i < 1000000; ++i)
    {
        l.set_size(i%100 + 1);
        l2.ParseText_pool();
    }

    endTime = (float)clock()/CLOCKS_PER_SEC;

    printf("with pool, time: %f\n", endTime - startTime);
};

在我的机器上运行 coliru ,说明分配越频繁,使用内存池的优势越大。

关于c++ - 使用 boost.pool 而不是 'new' 作为对象容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23199257/

相关文章:

c++ - 大部分使用 if 和 else 语句的程序没有正确执行

python - 使用 SWIG 公开 boost uuid

c++ - 将类型转换为 python

python 多处理池.starmap 不起作用

c++ - C++ inFile.Read中大小后跟多个参数

c++ - 我要求用户输入大小和数组,但是在打印 vector 时,它仅将 '0'显示为输出

C++——向私有(private)成员字段 std::vector 添加元素

C++ Boost - 无法解析命名空间成员或容器

python - 从单个 FTP 服务器进行多线程/异步下载

design-patterns - 池和集群的区别