繁体   English   中英

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

[英]Dealing with std::string/std::vector member variables while using boost::singleton_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);
}

我最近发布了一个关于使用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类型作为成员)使用相同的内存池? 如果是这样,我如何确保他们以某种方式做?

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

我从未研究过boost的那一部分,但是如果你想改变字符串分配内存的位置,你需要在编译时将不同的分配器传递给std::basic_string<> 没有其他办法。 但是,您需要注意其缺点:例如,此类字符串将不再分配给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不同。 使用动态分配字符串类的重点是它适应任何字符串长度。 所需的内存块大小不同(否则你可能只是char数组)。 我认为池分配器没有足够的空间来改进通用分配器。


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

在你的类中使用std::string / std::vector的自定义分配器可以工作(假设分配器是正确的) - 但只有性能测试才能看到你是否真正看到它的任何好处。

或者,如果您知道std::string / std::vector将具有上限,则可以在std::array (或正常数组,如果您没有c ++ 11)周围实现一个瘦包装器它是一个替代品。

即使大小是无限制的,如果有一些大小, 大多数值都会小于,你可以扩展基于std::array的实现,通过分配你的池化分配器,如果它们填满,可以扩展。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM