повысить multi_index_container и стереть производительность - PullRequest
2 голосов
/ 14 мая 2010

У меня есть бустер multi_index_container, объявленный как показано ниже, который индексируется по идентификатору hash_unique (long без знака) и идентификатору транзакции hash_non_unique (long). Вставка и извлечение элементов происходит быстро, но когда я удаляю элементы, это происходит намного медленнее. Я ожидал, что это будет постоянное время, поскольку ключ хешируется.

например, чтобы стереть элементы из контейнера

для 10000 элементов, это занимает около 2,53927016 секунд

для 15 000 элементов, это занимает около 7,137100068 секунд

для 20 000 элементов, это занимает около 21,391720757 секунд

Я что-то упускаю или ожидаемое поведение?

class Session
{
  public:
    Session() {
      //increment unique id
      static unsigned long counter = 0;
      boost::mutex::scoped_lock guard(mx);
      counter++;
      m_nId = counter;
    }

    unsigned long GetId() {
     return m_nId;
    }
    long GetTransactionHandle(){
    return m_nTransactionHandle;
    }
    ....
private:
  unsigned long m_nId;
  long m_nTransactionHandle;
  boost::mutext mx;
  ....
};
typedef multi_index_container<
  Session*,
  indexed_by< 
    hashed_unique< mem_fun<Session,unsigned long,&Session::GetId> >,
    hashed_non_unique< mem_fun<Session,unsigned long,&Session::GetTransactionHandle> >
    >  //end indexed_by
  > SessionContainer;
typedef SessionContainer::nth_index<0>::type SessionById;


int main() {
  ...
   SessionContainer container;
   SessionById *pSessionIdView = &get<0>(container);
   unsigned counter = atoi(argv[1]);
   vector<Session*> vSes(counter);
   //insert
   for(unsigned i = 0; i < counter; i++) {
     Session *pSes = new Session();
     container.insert(pSes); 
     vSes.push_back(pSes);
   }
   timespec ts;
   lock_settime(CLOCK_PROCESS_CPUTIME_ID, &ts);
   //erase
   for(unsigned i = 0; i < counter; i++) {
      pSessionIdView->erase(vSes[i]->getId());
      delete vSes[i];
   }
   lock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
   std::cout << "Total time taken for erase:" << ts.tv_sec << "." << ts.tv_nsec << "\n";
   return (EXIST_SUCCESS);
}

Ответы [ 3 ]

3 голосов
/ 15 мая 2010

В вашем тестовом коде какое значение для m_nTransactionHandle получают объекты Session? Может быть, это одинаковое значение для всех объектов? Если это так, стирание займет много времени, поскольку производительность хэшированных контейнеров низкая, когда имеется много равных элементов. Попробуйте назначить различные значения m_nTransactionHandle при создании, чтобы увидеть, ускоряет ли это ваш тест.

0 голосов
/ 17 мая 2010

Я только что обнаружил, что производительность для hashed_non_unique по сравнению с hashed_unique для 2-го индекса практически одинакова, за исключением незначительных накладных расходов на проверку дубликатов.

Узкое место было с boost :: object_pool. Я не знаю внутреннюю реализацию, но кажется, что это список, в котором он перебирает список, чтобы найти объекты. См. Ссылку на результаты производительности и исходный код.

http://joshitech.blogspot.com/2010/05/boost-object-pool-destroy-performance.html

0 голосов
/ 17 мая 2010

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

...