boost的multi_index性能测试
上一篇我们总结了boost的multi_index的各种使用方法
这一篇我们测试下boost的实际性能如何,从插入,查询,删除等几个方面进行测试
结论如下:
1. multi_index的性能比STL的map性能较差,不过也在同一个数量级上
2. multi_index的删除效率较差,大概比插入效率低了25倍
3. multi_index的插入,查询在debug模式下效率很差,在release模式下效率非常高,差距超过10倍!删除效率倒是相差不大
原因详情可见: https://david-joe2005.iteye.com/blog/487391
实验如图:
Debug模式: Release模式:
完整测试代码如下:
#include <cstdio>
#include <map>
#include <vector>
#include <string>
#include <sstream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/smart_ptr.hpp>
#include <iostream>
#include <boost/progress.hpp>
using boost::multi_index_container;
using namespace boost::multi_index;
using namespace std;
using namespace boost;
// 玩家信息
class CPlayer
{
public:
CPlayer(int id, string name):id(id),name(name)
{
}
int id; // 唯一id
string name; // 名字
};
struct id{};
struct name{};
// 定义player容器
typedef boost::multi_index_container<
CPlayer,
indexed_by
<
ordered_unique<tag<id>, BOOST_MULTI_INDEX_MEMBER(CPlayer, int, id)>,
ordered_non_unique<tag<name>, BOOST_MULTI_INDEX_MEMBER(CPlayer, string, name)>
>
> PlayerContainer;
typedef map<int,CPlayer*> Map_Id_Player;
typedef map<string,CPlayer*> Map_Name_Player;
typedef vector<CPlayer*> Vec_Player;
int main()
{
PlayerContainer playerContiner; // 容器
Map_Id_Player mapIdPlayer; // map id->player
Map_Name_Player mapNamePlayer; // map name->player
// 100万次测试
int testNum = 1000000;
Vec_Player vecPlayer;
// 初始化
for(int i=0;i<testNum;i++)
{
vecPlayer.push_back(new CPlayer(i,"player"));
}
// 随机打乱
std::random_shuffle(vecPlayer.begin(), vecPlayer.end());
cout<<"开始测试:执行次数:"<<testNum<<endl;
///////////////////////////////// 插入测试 /////////////////////////////////
{
cout<<"multi_index插入耗时:";
progress_timer t;
for (Vec_Player::iterator iter=vecPlayer.begin();iter!=vecPlayer.end();iter++)
{
playerContiner.insert(**iter);
}
// progress_timer变量会在创建时计时,析构时自动打印出耗时,下同,不再解释
}
{
cout<<"map插入耗时:";
progress_timer t;
for (Vec_Player::iterator iter=vecPlayer.begin();iter!=vecPlayer.end();iter++)
{
mapIdPlayer.insert(Map_Id_Player::value_type((*iter)->id,*iter));
mapNamePlayer.insert(Map_Name_Player::value_type((*iter)->name,*iter));
}
}
///////////////////////////////// 查询测试 /////////////////////////////////
{
cout<<"multi_index查询耗时:";
progress_timer t;
PlayerContainer::index<id>::type& player_ID = playerContiner.get<id>();
PlayerContainer::index<name>::type& player_NAME = playerContiner.get<name>();
for (Vec_Player::iterator iter=vecPlayer.begin();iter!=vecPlayer.end();iter++)
{
player_ID.find((*iter)->id);
player_NAME.find((*iter)->name);
}
}
{
cout<<"map查询耗时:";
progress_timer t;
for (Vec_Player::iterator iter=vecPlayer.begin();iter!=vecPlayer.end();iter++)
{
mapIdPlayer.find((*iter)->id);
mapNamePlayer.find((*iter)->name);
}
}
///////////////////////////////// 删除测试 /////////////////////////////////
{
cout<<"multi_index删除耗时:";
progress_timer t;
PlayerContainer::index<id>::type& player_ID = playerContiner.get<id>();
for (Vec_Player::iterator iter=vecPlayer.begin();iter!=vecPlayer.end();iter++)
{
player_ID.erase(player_ID.find((*iter)->id));
}
}
{
cout<<"map删除耗时:";
progress_timer t;
for (Vec_Player::iterator iter=vecPlayer.begin();iter!=vecPlayer.end();iter++)
{
Map_Id_Player::iterator result1 = mapIdPlayer.find((*iter)->id);
if (result1 != mapIdPlayer.end())
{
mapIdPlayer.erase(result1);
}
Map_Name_Player::iterator result2 = mapNamePlayer.find((*iter)->name);
if (result2 != mapNamePlayer.end())
{
mapNamePlayer.erase(result2);
}
}
}
cout<<"结束测试:执行次数:"<<testNum<<endl;
getchar();
return 0;
}