提升multi_index_container和擦除性能

时间:2010-05-14 00:29:59

标签: boost

我有一个声明如下所述的boost multi_index_container,它由hash_unique id(unsigned long)和hash_non_unique事务id(long)索引。插入和检索元素很快,但是当我删除元素时,它要慢得多。我期待它是恒定的时间,因为关键是哈希。

例如从容器中删除元素

对于10,000个元素,大约需要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 个答案:

答案 0 :(得分:3)

在您的测试代码中,m_nTransactionHandle对象接收Session的值是多少?它可能是所有对象的相同值吗?如果是这样,擦除将花费很长时间,因为当存在许多相等的元素时,散列容器的性能很差。尝试在创建时分配不同的m_nTransactionHandle值,看看这是否加快了测试速度。

答案 1 :(得分:0)

当擦除元素时,性能是构成容器的所有索引的函数(基本上,元素必须从每个索引中删除,而不仅仅是您当前使用的索引) 。当存在许多等效元素时,散列指数会受到严重影响,这不是他们设计用来反对的模式。

答案 2 :(得分:0)

我刚刚发现,除了检查重复的轻微开销之外,第二个索引的hashed_non_unique与hashed_unique的性能几乎相同。

瓶颈在于boost :: object_pool。我不知道内部实现,但它似乎是一个列表,它遍历列表来查找对象。请参阅链接以获取性能结果和源代码。

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