> > OK, this seems to explain most of the issue.
> > What's the ratio t(multi_index)/t(manual) in debug and
> > release modes after suppresing safe mode and invariant-
> > checking?
In both cases the ratio is more or less the same. So, it is
between 3.28 and 3.62, depending of execution.
I have tested with only a ordered-unique index and the ratio
was 2.59, and also with only a hashed-unique index and the
result was 1.10.
[...]
> > Other than this I can't be much more helpful. If you're
> > in a position to provide me with a complete example program
> > that I can play with I'll sure have a deeper look.
Here you have it....
#include <boost/lexical_cast.hpp>
#include <sys/time.h>
#include <unistd.h>
#include <iostream>
#if defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
#include <map>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/composite_key.hpp>
using namespace boost::multi_index;
//////////////////////////////////////
// Types declarations
//////////////////////////////////////
enum PRIORITY_LEVEL {
PRIORITY_EXPRESS,
PRIORITY_HIGH,
PRIORITY_DEFAULT,
PRIORITY_LOW,
PRIORITY_NULL
};
struct TElementRec {
PRIORITY_LEVEL priority;
std::string key;
std::string content;
TElementRec():
priority(PRIORITY_DEFAULT){}
TElementRec( const PRIORITY_LEVEL &priority, const std::string &key, const std::string &content ):
priority(priority), key(key), content(content){}
TElementRec( const TElementRec &rec ) {
priority = rec.priority;
key = rec.key;
content = rec.content;
}
TElementRec & operator = ( const TElementRec &rec ) {
priority = rec.priority;
key = rec.key;
content = rec.content;
return( *this );
}
};
// Tags
struct TMainIndexTag{};
struct TKeyIndexTag{};
// Multi index container definition
typedef multi_index_container<
TElementRec,
indexed_by<
ordered_unique<
tag<TMainIndexTag>,
composite_key<
TElementRec,
BOOST_MULTI_INDEX_MEMBER(TElementRec,PRIORITY_LEVEL,priority),
BOOST_MULTI_INDEX_MEMBER(TElementRec,std::string,key)
>
>,
hashed_unique<
tag<TKeyIndexTag>,
BOOST_MULTI_INDEX_MEMBER(TElementRec,std::string,key)
>
>
> TElementsMIContainer;
// MANUAL DECLARATIONS
//////////////////////
struct TProcessRec {
std::string content;
TProcessRec() {
};
TProcessRec( const std::string &msg ) {
this->content = msg;
};
TProcessRec( const TProcessRec &pRec ) {
content = pRec.content;
}
TProcessRec & operator = ( const TProcessRec &pRec ) {
content = pRec.content;
return( *this );
}
};
struct QueueMsgKey {
std::string key;
PRIORITY_LEVEL priority;
QueueMsgKey(const std::string &_key, const PRIORITY_LEVEL &_priority) {
key = _key;
priority = _priority;
}
QueueMsgKey(const std::string &_key) {
key = _key;
priority = PRIORITY_DEFAULT;
}
QueueMsgKey() {
priority = PRIORITY_DEFAULT;
}
QueueMsgKey & operator = ( const QueueMsgKey &pRec ) {
priority = pRec.priority;
key = pRec.key;
return( *this );
}
};
struct QueueMsgKeyLess {
bool operator()(const QueueMsgKey k1, const QueueMsgKey k2) const
{ return k1.priority!=k2.priority ? k1.priority>k2.priority : k1.key<k2.key; }
};
struct MsgKeyLess {
bool operator()(const std::string k1, const std::string k2) const
{ return k1<k2; }
};
typedef std::map< QueueMsgKey, TProcessRec, QueueMsgKeyLess > TInProcessList;
typedef std::map< QueueMsgKey, TProcessRec, QueueMsgKeyLess > :: iterator TProcessListIterator;
typedef std::map< std::string, TProcessListIterator, MsgKeyLess > TRefList;
typedef std::map< std::string, TProcessListIterator, MsgKeyLess > :: iterator TRefListIterator;
//////////////////////////////////////
// Code
//////////////////////////////////////
int getMicroSecondsPassed( int ×tamp, int µSeconds )
{
int lTimestamp = time(NULL);
struct timeval tv;
gettimeofday(&tv, NULL);
char msecs[ 20 ];
sprintf( msecs, "%d", tv.tv_usec );
std::string strMSecs = msecs;
int lMicroSeconds = boost::lexical_cast<int>( strMSecs );
if ( !timestamp ) {
timestamp = lTimestamp;
microSeconds = lMicroSeconds;
return 0;
}
return (lTimestamp-timestamp)* 1000000 + (lMicroSeconds-microSeconds);
}
bool insert(const QueueMsgKey &qkey, const TProcessRec &data)
{
TInProcessList process_list;
TRefList ref_list;
TRefListIterator itr = ref_list.find( qkey.key );
if ( itr == ref_list.end() ) {
std::pair< TProcessListIterator, bool > result = process_list.insert( std::make_pair( qkey, data) );
if(result.second == true) {
ref_list[qkey.key] = result.first;
return true;
}
else {
return false;
}
}
return false;
}
int main( int argc, char** argv ){
int firstTime = 0;
int firstMicroSeconds = 0;
TElementsMIContainer elMIContainer;
PRIORITY_LEVEL priority = PRIORITY_DEFAULT;
std::string content = "...";
std::string key;
// Multi-index container performance test
////////////////////////////////////////////
getMicroSecondsPassed( firstTime, firstMicroSeconds );
for ( int i=0; i<100000; i++ ) {
// Changing only the key
key = "A0000" + boost::lexical_cast<std::string>(i);
elMIContainer.insert( TElementRec( priority, key, content ));
}
int multiindexTime = getMicroSecondsPassed( firstTime, firstMicroSeconds );
std::cout << "<TQueueScheduler> Total microseconds : " << multiindexTime << std::endl;
firstTime = 0;
firstMicroSeconds = 0;
// Manual containers performance test
////////////////////////////////////////////
getMicroSecondsPassed( firstTime, firstMicroSeconds );
for ( int i=0; i<100000; i++ ) {
// Changing only the key
QueueMsgKey qack_key( "A0000" + boost::lexical_cast<std::string>(i) );
insert( qack_key, TProcessRec( "..." ) );
}
int manualTime = getMicroSecondsPassed( firstTime, firstMicroSeconds );
std::cout << "<TOutProcessList> Total microseconds : " << manualTime << std::endl;
std::cout << "RATIO=" << (float)multiindexTime / manualTime << std::endl;
}
Thanks a lot for your time