Быстрый способ удалить записи вектора STL из указателей

У меня есть вектор указателей, которые я хочу удалить, но перебирая вектор и вызывая delete для каждого элемента довольно медленно. Есть ли более быстрый способ?

К сожалению, мне действительно нужно хранить указатели, поскольку я использую виртуальный суперкласс. Упрощенно, структура классов выглядит примерно так:

class VirtualSuperClass
{
protected:
    SomeType m_someMember;
    // ...
public:
    virtual void doSomething() = 0;
};

class Subclass_1 : public VirtualSuperClass
{
protected:
    SomeType m_someSubclassMember;
    // ...
public:
    virtual void doSomething() { /* do something*/ }
};

class Subclass_2 : public VirtualSuperClass
{
protected:
    SomeType m_someOtherSubclassMember;
    // ...
public:
    virtual void doSomething() { /* do something else*/ }
}

В моем основном методе я заполняю вектор указателей суперкласса и вызываю функцию doSomething() для каждого элемента.

int main()
{
    std::vector<VirtualSuperClass*> vec;
    vec.push_back(new Subclass_1());
    vec.push_back(new Subclass_2());
    vec.push_back(new Subclass_2());
    vec.push_back(new Subclass_1());
    // and so on, about 40,000 elements (not really done with .push_back :) ) ...

    // this actually runs in an application loop
    for (size_t i = 0; i < vec.size(); i++)
    {
        vec[i]->doSomething();
    }

    // ...

    for (size_t i = 0; i < vec.size(); i++)
    {
        delete vec[i];     // <-- pretty slow for large number of elements
        vec[i] = NULL;
    }
    vec.clear();
    return 0;
}

3 ответа

Решение

Одна вещь, которую вы можете искать, это пользовательский распределитель для классов, которые вы выделяете - таким образом, вы можете эффективно получать и высвобождать память для системы в большом количестве, а не в маленьких фрагментах - это, вероятно, единственное решение для улучшения "общей" производительности этого система без ее изменения (что, учитывая ваше узкое место, безусловно, выглядит хорошей идеей;)).

Любое правильное решение сводится к delete на каждом указателе. Поскольку вы профилировали свой код и определили, что это является узким местом, я бы искал решение, которое бы delete в другую ветку.

Это может быть сделано:

  1. Создать рабочий поток, который deleteуказатели переданы в
  2. Удалите указатели из вектора и скопируйте их в другой вектор, принадлежащий рабочему потоку.
  3. Начните задание рабочего потока, позвольте ему удалить указатели

Это не будет быстрее, чем ваше текущее решение, с точки зрения чистого процессорного времени (и на самом деле может быть медленнее, в зависимости от того, как вы это делаете), но это переместит тяжелую работу из вашего основного потока.

Другой метод, который может улучшить производительность, - это использовать пул памяти, в котором вы выделяете один большой необработанный буфер, а затем размещаетеnew каждый отдельный объект в этом буфере.

Это может повысить производительность, потому что, хотя вам все еще нужно уничтожить каждый указатель, это уничтожение выполняется посредством прямого вызова деструктора, а не deleteэто Это позволяет избежать необходимости обращаться к диспетчеру памяти системы, и именно в этом случае возможны улучшения производительности.

Однако у этого подхода есть существенные недостатки, и я бы не рекомендовал его ни в каких, кроме самых крайних случаях. Среди предостережений - обременительная ответственность, которую вы возлагаете на себя, чтобы управлять своей собственной памятью.

Другие вопросы по тегам