2

現在、私が書いたライブラリでは、私の小さなオブジェクト (ポリモーフィックではない) は、オブジェクト プール内でunique_ptr's を持つベクトルに割り当てられます。new を何度も呼び出すと明らかに多くのオーバーヘッドがあるため、明らかにこれを変更したいと考えています。vector<Object>オブジェクトをプールにキャッシュする (つまり、ベクトルに格納する) か、必要なときに ID を介してオブジェクトを作成する方が効率的かどうかに興味があります。そして、作成されるオブジェクトがたくさんあることに注意してください。

つまり、これを行う必要があります。

必要に応じてオブジェクトを作成しますか? (すべて含まれているのは ID と親オブジェクトへの参照/ポインターであるため、これらのオブジェクトは 64 ~ 128 ビットと小さいことに注意してください)

Object ObjectFactory::create()
{
    return Object(nextId(), getParent());
}

Object ObjectFactory::get(unsigned id)
{
    return Object(id, getParent());
}

また:

Object& ObjectFactory::create()
{
     // get the next id of the object
     unsigned id = nextId();

     // resize (if necessary)
     if(_objects.size() <= id)
     {
        _objects.resize(id + 1);
        _objects[id]._parent = getParent();
     }

     return _objects[id];
}

Object& ObjectFactory::get(unsigned id)
{ return _objects[id]; }

私が特に懸念しているのは、 の再作成Objectによって多くのオーバーヘッドが発生するかどうかです。

4

1 に答える 1

0

@LokiAstariは正しいです。サイズ変更時のポインターに問題があることは明らかです。

わからないことがあります。あなたはオブジェクト プールを使用しているが、新しいステートメントが多すぎることに問題があると言っています。オブジェクト プールを使用している場合、それはまさに新しいステートメントを避けるためだと思いますよね?

ここに私の提案がありますが、私は専門家ではなく、通常は独自のアロケーターの実装を含むより良い解決策があるかもしれません (力の暗い側面..)。のようなコンテナーを使用できますstd::deque。これにより、サイズ変更時のポインター/参照の有効性が保証されます。

多数のオブジェクト (プール) の最初のサイズ変更から開始し、必要に応じて後続のサイズ変更を手動で処理する (事前定義されたサイズのチャンクで容量を拡張する) か、必要があることがわかっている場合は新しいステートメントを受け入れることができます。 emplace_back メソッドを使用してください。

また、ID を使用してオブジェクトの挿入/削除を頻繁に行っているかどうかもわかりません。もしそうなら、あなたは使用を検討するかもしれませんstd::unordered_map

を使用した例を次に示しstd::dequeます。

#include <iostream>
#include <deque>

#define POOL_RESERVE 1000


// Data storage for your object
struct MyObjectData
{
    double some_data;
};


// Container returned by the factory
struct MyObject 
{
    typedef MyObjectData data_type;

    unsigned   id; 
    data_type* data;

    MyObject(): id(0), data(0) {}
    MyObject( const unsigned& id_, data_type* data_ ): id(id_), data(data_) {}

    void set( const unsigned& id_, data_type* data_ )
        { id = id_; data = data_; }
};


// MyObject Pool
class MyObjectPool
{
public:

    typedef MyObjectData data_type;

    MyObjectPool(): count(0) { pool.resize(POOL_RESERVE); }

    void get( const unsigned& id, MyObject& obj )
        {
            // Check requested index
            if ( id >= count )
                obj.set( 0, 0 );
            else
                obj.set( id, &pool[id] );
        }

    void create( MyObject& obj )
        {
            // Create new data container if needed
            if ( count++ >= pool.size() ) pool.emplace_back();

            // Return next available object
            obj.set( count-1, &pool[count-1] );
        }

private:

    unsigned count;
    std::deque<data_type> pool;
};


// MyObject factory
class MyObjectFactory
{
    typedef MyObjectFactory self;
    static MyObject local;

    static MyObjectPool& get_instance()
        {
            static MyObjectPool pool; 
            return pool;
        }

public:

    static MyObject get( const unsigned& id )
        {
            self::get_instance().get(id,local);
            return local;
        }

    static MyObject create()
        {
            self::get_instance().create(local);
            return local;
        }
};

// Define static variable
MyObject MyObjectFactory::local = MyObject();


// Usage example
int main()
{
    MyObject a,b,c;

    a = MyObjectFactory::create();
    b = MyObjectFactory::create();
    c = MyObjectFactory::get(1);
}
于 2013-02-05T15:55:45.030 に答える