使用boost :: singleton_pool时处理std :: string/std :: vector成员变量

san*_*ank 9 c++ memory-management boost-pool

我正在编写一个性能关键型应用程序,我在其中创建大量类似类型的对象来下订单.我使用boost :: singleton_pool来分配内存.最后我的班级看起来像这样.

    class MyOrder{
    std::vector<int> v1_;
    std::vector<double> v2_;

    std::string s1_;
    std::string s2_;

public:
    MyOrder(const std::string &s1, const std::string &s2): s1_(s1), s2_(s2) {}

    ~MyOrder(){}

    static void * operator new(size_t size); 
    static void operator delete(void * rawMemory) throw();
    static void operator delete(void * rawMemory, std::size_t size) throw();

};

struct MyOrderTag{};
typedef boost::singleton_pool<MyOrderTag, sizeof(MyOrder)> MyOrderPool; 

void* MyOrder:: operator new(size_t size)
{
    if (size != sizeof(MyOrder)) 
        return ::operator new(size);

    while(true){
        void * ptr = MyOrderPool::malloc();
        if (ptr != NULL) return ptr;

        std::new_handler globalNewHandler = std::set_new_handler(0);
        std::set_new_handler(globalNewHandler);

        if(globalNewHandler)  globalNewHandler();
        else throw std::bad_alloc();

    }
}

void MyOrder::operator delete(void * rawMemory) throw()
{
    if(rawMemory == 0) return; 
    MyOrderPool::free(rawMemory);
}

void MyOrder::operator delete(void * rawMemory, std::size_t size) throw()
{
    if(rawMemory == 0) return;
    if(size != sizeof(Order)) {
        ::operator delete(rawMemory);
    }
    MyOrderPool::free(rawMemory);
}
Run Code Online (Sandbox Code Playgroud)

我最近发布了一个关于使用boost :: singleton_pool的性能优势的问题.当我比较boost :: singleton_pool和默认分配器的性能时,我没有获得任何性能优势.当有人指出我的类有std :: string类型的成员,其分配不受我的自定义分配器的控制时,我删除了std :: string变量并重新进行了测试.这次我注意到了相当大的性能提升.

  1. 现在,在我的实际应用中,我无法摆脱时间std :: string和std :: vector的成员变量.我应该在我的std :: string和std :: vector成员变量中使用boost :: pool_allocator吗?

  2. boost :: pool_allocator从底层std :: singleton_pool分配内存.如果不同的成员变量(我的MyOrder类中有多个std :: string/std :: vector类型.重要的是.我还使用了除MyOrder以外的类的池,其中包含std :: string/std :: vector类型作为成员)使用相同的内存池?如果是这样,我如何确保他们以某种方式做?

sbi*_*sbi 2

  1. 现在,在我的实际应用程序中,我无法摆脱 time std::string 和 std::vector 的成员变量。我应该将 boost::pool_allocator 与 std::string 和 std::vector 成员变量一起使用吗?

std::basic_string<>我从来没有研究过 boost 的这一部分,但是如果你想改变字符串分配内存的位置,你需要在编译时传递一个不同的分配器。没有其他办法。但是,您需要意识到这样做的缺点:例如,此类字符串将不再可分配给std::string。(虽然雇佣c_str()是可行的,但它可能会带来一点性能损失。)

  1. boost::pool_allocator 从底层 std::singleton_pool 分配内存。如果不同的成员变量(我的 MyOrder 类中有多个 std::string/std::vector 类型)会很重要吗?此外,我还为除 MyOrder 之外的包含 std::string/std::vector 类型的类使用池作为成员)使用相同的内存池?如果确实如此,我如何确保他们以一种或另一种方式行事?

池的全部意义在于将多个对象放入其中。如果只有一个,就不需要游泳池了。所以,是的,你可以把几个对象放进去,包括几个对象的动态内存std::string

然而,这是否会给您带来任何性能提升还有待观察。您使用池是因为您有理由假设它比通用分配器更快(而不是使用它来从特定区域分配内存,例如共享内存)。通常这样的池速度更快,因为它可以假设其中分配的对象的大小。对于您的类来说当然是这样MyOrder:它的对象始终具有相同的大小,否则(较大的派生类)您将不会在池中分配它们。
这对于 来说是不同的std::string。使用动态分配字符串类的要点在于它可以适应任何字符串长度。所需的内存块大小不同(否则您可以只使用字符数组)。我认为池分配器比通用分配器改进的空间很小。


附带说明:您的重载operator new()返回调用全局结果的结果,但您operator delete只是将任何传入该池的free(). 这对我来说似乎很可疑。