Обновить
9

Пользователь

1
Подписчики
Отправить сообщение
Перегрузка new/delete выглядит интересно. Но… а как параметры передавать конструктору Data* data = new Data(10, 20)?
Впрочем оно и так не было быстрее прямого создания в векторе :) Если ещё покажете как можно такой же фокус проделать с указателями, вообще перевернете мои представление о бытии :))

P.S. Просто брать указатель на только что добавленый через emplace_back объект нельзя, ибо если вектор содержащий объект, куда то скопировать/переместить — указатель будет валидным лишь для источника, что естественно.
PoolFactory<BaseClass> bPool;

  {
    std::vector< BaseClass* > ptr_ar;
    ptr_ar.reserve(total);
    /// PoolFactory 
    bPool.freeAll();
  }

  {
    std::vector< BaseClass* > ptr_ar;
    ptr_ar.reserve(total);
    /// PoolFactory 2
    bPool.freeAll();
  }


Здесь для чистоты эксперимента, раз уж мы «прогреваемся» следует и std::vector< BaseClass* > ptr_ar; вынести:
    PoolFactory<BaseClass> bPool;
    std::vector< BaseClass* > ptr_ar;

  {
    ptr_ar.reserve(total);
    /// PoolFactory 
    bPool.freeAll();
  }

  {
    ptr_ar.reserve(total);
    /// PoolFactory 2
    bPool.freeAll();
  }


Пул от того выигрывать не станет, но по крайне мере проигрывает не так сильно :)
Насчет прогрева — в моём понимании reserve именно и должен был выполнить «прогрев». Попробовал ваш код. Получил несколько более медленное заполнение с пулом чем с emplace_back (порядка 5% разницы). Но вот при повторном проходе удивился — с пулом НЕ стало быстрее. Причина тому, то что при get() — пул инициализирует объект вызывая конструктор. Попробовал сравнивать emplace_back() и getRaw() — пул так же не выигрывает в скорости по сравнению с прямой emplace_back. Этого я уже объяснить не могу, учитывая тот факт что new в лоб явно не быстрее изъятия из пула.

Чем по вашему вызван подобный «прогрев», имею ввиду при повторном проходе? Ведь мы зарезервировали память изначально с reserve.

Читал про Александреску. Его книгу не читал. Вообще не люблю книги.
Спасибо, буду знать.
Спасибо — буду знать.
Могу выложить qt проект — потестируете.
Мне же Буст встраивать в целевой проэкт не представляется возможным :) Хотел ptr_vector из библиотеки только вырвать — так там туча зависимостей. На этом моё знакомство с бустом закончилось :).
Про локи первый раз слышу :) (ну может второй)
Вы имели ввиду наверное это (действительно перепутал с reserve):
    void makeMore(){
        int init_size = buffers.size();
        int target_size = buffers.size() + chunk_size;
        buffers.resize(target_size);

        for (int i = init_size; i < target_size; ++i) {
            //buffers.emplace_back();
            free_ptrs.emplace_back(&buffers[i]);
        }
    }


Как ни странно — скорость выполнения все ещё ниже чем предложенным в статье способом.
Не равно. vector перемещает массив каждый раз при увеличении. Потому если заранее известен размер — имеет смысл reserve. Если все правильно то благодаря reserve перемещения массива можно избежать вообще.
Верно — путаю :)
Попробуйте убрать emplace_back и поймете в чем дело :)
resize() — всего лишь выделяет память. Но не создает новый объект.
Собственно объект создает (и добавляет элемент, и увеличивает size() ) — emplace_back/push_back
Мне почему то всегда казалось, что std::deque — это двухсвязаный список, тоесть есть издержки и на добавление и на поиск. Но перечитав документацию на него понял что ошибался.

Тем не менее — только что проверил — быстрее не оказалось:

template <typename T, unsigned int chunk_size = 100>
class PoolDeque
{
public:
    PoolDeque(){}

    inline T* get(){
        if(free_ptrs.empty()){
            makeMore();
        }

        T* obj = free_ptrs.back();
        free_ptrs.pop_back();
        return obj;
    }

    inline void free(T* obj){
        free_ptrs.push_back(obj);
    }

    void clearPool(){
        buffers.clear();
        free_ptrs.clear();
    }

private:

    std::deque<T>  buffers;
    std::vector<T*> free_ptrs;

    void makeMore(){
        buffers.resize(buffers.size() + chunk_size);

        for (int i = 0; i < chunk_size; ++i) {
            buffers.emplace_back();
            free_ptrs.emplace_back(&buffers.back());
        }
    }
};


Результаты (с декой — 5й):
1: 94
2: 64
3: 35
4: 140
5: 99
12 ...
12

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность