简体   繁体   中英

How to make sure each 100 objects of given type are allocated in contiguous memory?

I have a type. I instantiate it in different parts of my application yet I iterate over all of them sequentially at some place. I do not know how many there will be in the end. How can I create an allocator that would store blocks of 100 objects and provide me with pointers on demand?

I have tried such approach with a simple factory on steroids yet it goes over 5 seconds :

#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <thread>
#include <mutex>

using namespace std;

template<class T>
struct Item {
    T data;
    bool alive = true;
    int id = 0;
};

template<class T>
class ItemFactory {
    vector<Item<T>> items;
    unordered_map<int, int> item_ids;
    unsigned int lastCounter=0;
    int removedCounter=0;
    mutex m;

    public:
    int CreateItem() {
        lock_guard<mutex> l(m);
        auto result = lastCounter++;
        Item<T> item;
        item.id = result;
        items.push_back(item);
        item_ids[result] = items.size()-1;
        return result;
    }

    T& GetItem(int id) {
        lock_guard<mutex> l(m);
        return items[item_ids[id]].data;
    }

    void RemoveItem(int id) {
        lock_guard<mutex> l(m);
        items[item_ids[id]].alive = false;
        removedCounter++;

        if(removedCounter>=1000) {
            removedCounter = 0;
            auto end = remove_if(items.begin(), items.end(), [](const Item<T>& item){
                return !item.alive;
            });
            items.erase(end, items.end());
            auto size = items.size();
            item_ids.clear();
            for(auto i = 0; i < size; i++) {
                item_ids[items[i].id]=i;
            }
        }
    }

};

struct demo {
    string bla;
    float arr[256];
};

int main() {
    ItemFactory<demo> f;
    for(int i = 0; i < 50000; i++) {
        auto id = f.CreateItem();
        auto id2 = f.CreateItem();
        auto & i1 = f.GetItem(id);
        auto & i2 = f.GetItem(id2);
        i1.bla = "abra kadabra bum";
        i2.bla = "bla bla bla";
        f.RemoveItem(id);
    }
    cout << "!!!" << endl;
    for(int i = 0; i < 25000; i++) {
        auto id = i + i*2;
        auto & i1 = f.GetItem(id);
        i1.bla = "abra kadabra bum";
        f.RemoveItem(id);
    }
    return 0;
}

Is there any way to get continuos chunks of memory yet be more effective on insertion/removal?

I would look up how to write a memory pool allocator, or use one of the many available, such as Boost Pool: http://www.boost.org/doc/libs/1_59_0/libs/pool/doc/html/index.html

C++11 memory pool design pattern?

In general, you allocate large chunks of memory and hand out pointers as you need them; it can be optimised if you know you're never going to free memory. If you really need contiguous memory all of the time, even if you're freeing occasionally, the only thing you can do is reallocate the memory and reshuffle objects, which can be very expensive if done often.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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