Мой текущий проект реализует пул объектов, чтобы избежать постоянного выделения памяти и выделения ресурсов для целей скорости, пул объектов является std::vector<object>
и я хотел бы реализовать форму сборки мусора, чтобы уменьшить использование памяти и повысить производительность. Каждый цикл, в котором программа выполняет итерацию по всему вектору, и если объект активен, выполняет функцию обновления, это означает, что если мой вектор заполнен неактивными объектами, я буду тратить много времени на итерации по ним, а также на их сохранение в памяти. Я не могу очистить вектор каждый кадр, так как это снизит производительность.
Моя текущая попытка реализовать это состояла в том, чтобы измерить время обновления и использовать предопределенную функцию, чтобы определить, тратим ли мы слишком много времени на обновление, для количества объектов, активных в настоящее время, если мы, я очищаю вектор один раз, чтобы позволить скорости вернуться к нормальной жизни.
#include <chrono>
void updateObjects()
{
auto begin = std::chrono::high_resolution_clock::now();
//update all objects
for(auto o : objectVec)
{
//only update active objects
if(o.m_alive)
{
o.update();
}
}
//end time of update
auto end = std::chrono::high_resolution_clock::now();
//calculate time taken vs estimated time
auto elapsed = (end-begin).count();
//Estimate is based on performance testing
long estimate = 25*m_particleCount+650000;
//If we have no active objects,
//but are wasting memory on storing them, we clean up
//If the update takes longer than it should, we clean up
if(((objectCount <= 0) && (objectVec.size() > 0)) || (elapsed > estimate))
{
cleanVec(); //remove inactive objects
}
}
Это решение хорошо работает на моем компьютере, однако у меня возникают проблемы с ним на других компьютерах, так как время, необходимое для завершения обновления, меняется из-за разной скорости процессора, и моя предопределенная функция не работает, так как она основана на неверных данных. Мне интересно, есть ли другое измерение, которое я могу использовать для этого расчета? Есть ли способ, которым я могу измерить чистое количество выполненных инструкций, так как это будет одинаково для разных компьютеров, некоторые просто выполнят их быстрее? Любые другие предложения приветствуются, спасибо!
Пул объектов может быть до 100 000 объектов, типичное использование будет варьироваться от 3000 до максимума.
Моя функция для очистки:
objectVec.erase(std::remove_if(objectVec.begin(),
objectVec.end(),
[](const object& o) {return !(o->m_alive);}),
objectVec.end());
Как правило, пул объектов использует старение определить, когда выгонять отдельный объект пула.
Один из способов сделать это — сохранить счетчик итераций в цикле обновления. Этот счетчик будет увеличиваться каждый цикл. Каждый объект может сохранять «последнее активное» время (количество циклов, когда объект был активен в последний раз). Неактивные объекты будут перемещены в конец массива, а когда достаточно старый будет удален (уничтожен). Отдельный индекс последнего активного объекта будет сохранен, поэтому цикл обновления может прекратиться, когда это встретится.
Если невозможно сохранить активное время в объекте, вы все равно можете переместить неактивные объекты в конец активного списка, и, если слишком много неактивных объектов, уменьшите некоторые из списка.
Вы должны указать, сколько стоит ваша очистка, и насколько велик ваш пул, они влияют на то, как следует проводить очистку.
Чтобы было ясно, пул фактически является распределителем объектов одного типа, и выигрыш в производительности полностью не зависит от того, как очищаются отдельные объекты.
Я не могу очистить вектор каждый кадр, так как это снизит производительность.
Если производительность очистки неактивных объектов доминирует, вы ничего не можете сделать в алгоритме пула.
Поэтому я предполагаю, что это связано с std::vector
семантика, при которой удаление неактивных объектов подразумевает перемещение других объектов. Тогда логично спросить, действительно ли вам нужно std::vector
свойства?
std::vector
Это хорошо.Если ответ нет, то просто используйте такие вещи, как std::deque
а также std::list
где удаление O (1), и вы можете очистить на каждом кадре.
В противном случае сборка мусора в вашем пуле может быть выполнена как