我正在编写一个性能关键型应用程序,我在其中创建大量类似类型的对象来下订单。我使用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);
}
我最近发布了question关于使用boost :: singleton_pool的性能优势。当我比较boost::singleton_pool和默认分配器的性能时,我没有获得任何性能优势。当有人指出我的类有std :: string类型的成员,其分配不受我的自定义分配器的控制时,我删除了std :: string变量并重新进行了测试。这次我注意到了相当大的性能提升。
现在,在我的实际应用中,我无法摆脱时间std :: string和std :: vector的成员变量。我应该在我的std :: string和std :: vector成员变量中使用boost::pool_allocator吗?
boost :: pool_allocator从底层std :: singleton_pool分配内存。如果不同的成员变量(我的MyOrder类中有多个std :: string / std :: vector类型。重要的是。我还使用了除MyOrder以外的类的池,其中包含std :: string / std :: vector类型作为成员)使用相同的内存池?如果是这样,我如何确保他们以某种方式做?
答案 0 :(得分:2)
- 现在,在我的实际应用中,我无法摆脱时间std :: string和std :: vector的成员变量。我应该在我的std :: string和std :: vector成员变量中使用boost :: pool_allocator吗?
醇>
我从未研究过boost的那一部分,但是如果你想改变字符串分配内存的位置,你需要在编译时将不同的分配器传递给std::basic_string<>
。没有其他办法。但是,您需要注意其缺点:例如,此类字符串将不再分配给std::string
。 (虽然使用c_str()
会起作用,但可能会造成很小的性能损失。)
- 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 delete
只会将任何内容传递到该池的free()
。这对我来说似乎很可疑。
答案 1 :(得分:1)
在您的类中使用std::string
/ std::vector
的自定义分配器可以正常工作(假设分配器是正确的) - 但只有性能测试才能看到您是否真的看到它带来任何好处。
或者,如果你知道std::string
/ std::vector
会有上限,你可以在std::array
周围实现一个瘦包装(如果没有c,可以实现普通数组) ++ 11)这使它成为替代品。
即使大小无限制,如果大多数值的某个大小小于,您可以通过分配您的池,将上面基于std::array
的实现扩展为可扩展的分配器,如果他们填满。