リストとマップの特定の使用方法のパフォーマンスを向上させたいと考えています。この場合、アイテムの数には 100000 のオーダーの厳しい制限があります。STL のデフォルト アロケータは明らかに、この状況では最良の選択ではありません。何千もの小さなオブジェクトすべてに非常に長い時間がかかります (>10 秒!)。他のすべての潜在的な問題は言うまでもありません。
したがって、明らかにこれを改善するために、すべてのリスト/マップ ノードを格納するための適切な量のメモリを事前に割り当てることができます。これまでのところ、(std::allocator_traits から派生することにより) デフォルト アロケータの動作バージョンを実装することができました。これは、各ノードに alloc/free を使用します。しかし、これを変更して、たとえば非常に単純なスタックを「ステートフル」に使用できるようにする方法を見つけるのに苦労しています。
using namespace std;
class MemPoolStack
{
public:
size_t Size;
size_t Mult;
size_t Total;
size_t Top;
size_t Last;
unique_ptr<byte[]> Data;
unique_ptr<size_t[]> Nexts;
MemPoolStack(size_t size, size_t mult) :
Size(size),
Mult(mult),
Total(size * mult),
Top(0),
Last(0),
Data(new byte[Total]),
Nexts(new size_t[Size])
{
}
size_t& Next(size_t i)
{
return *(Nexts.get() + i);
}
void* Pop()
{
byte* p = nullptr;
if(Top<Size)
{
p = Data.get() + (Top * Mult);
bool last = (Top==Last);
size_t next = last ? Top+1 : Next(Top);
if(last) Next(Top) = next;
Top = next;
if(Top>Last) Last=Top;
}
else
{
p = nullptr;
}
return p;
}
bool Push(void* p)
{
ptrdiff_t diff = (byte*)p - Data.get();
size_t index = ((size_t)diff / Mult);
if(diff>=0 && index<Size)
{
Next(index) = Top;
Top = index;
return true;
}
return false;
}
};
template <class T> struct MemPool
{
typedef T value_type;
MemPool() throw() {}
template <class U> MemPool (const MemPool<U>&) throw() {}
template <class U> struct rebind { typedef MemPool<U> other; }; //off-topic: why doesn't allocator_traits define this?
T* allocate (size_t n)
{
return static_cast<T*>(malloc(n*sizeof(T)));
}
void deallocate (T* p, size_t n)
{
free(p);
}
};
template <class T, class U>
bool operator== (const MemPool<T>&, const MemPool<U>&) throw()
{return true;}
template <class T, class U>
bool operator!= (const MemPool<T>&, const MemPool<U>&) throw()
{return false;}
そして、次のようにリストとマップをインスタンス化しています。
list<TKey, MemPool<TKey>> Keys;
map<TKey, MapType, less<TKey>, MemPool<MapType>> Map;
それMemPoolStack
自体はここでは実際の問題ではありません。おそらくバグがありますが、これは単なる例です。ポイントは、MemPoolStack
クラスunique_ptr
が事前に割り当てられたメモリと他のいくつかのメンバー変数に a を格納することです。
問題は、Visual C++11 マップまたはリストがアロケーターを構築できるさまざまな方法がすべて、リストまたはマップごとに 1 つのインスタンスになるようMemPoolStack
に、クラス内に my への参照が必要なことです。次に、 in 、およびinを使用できます。MemPool
MemPoolStack
MemPoolStack::Pop()
MemPool::allocate()
MemPoolStack::Push()
MemPool::deallocate()
サイズを指定して、アロケータを最初に構築する方法も必要です。を入れてみshared_ptr<MemPoolStack>
ましMemPool
たが、リストがアロケーターのデフォルトコンストラクターを呼び出すことを決定したときに失われました...
また、元の問題に対する優れた代替ソリューションを得るために、このコードをすべて破棄することにもオープンです。