我有一个声明如下所述的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);
}
答案 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