#include #include #include #include #include #include #include "util/SimpleLogger.hpp" #include "util/Stopwatch.hpp" #include "SharedMap.hpp" namespace // anonymous { Tony::SimpleLogger slog( "SharedMapTest", std::cerr ); // actual core random number generator boost::mt19937 rng; // distribution to pick letters at random boost::uniform_int<> alphaIxDist(0,25); // and an engine to tie the two together boost::variate_generator< boost::mt19937&, boost::uniform_int<> > alphaIxGen( rng, alphaIxDist ); std::string genRandomString( int meanLen = 10 ) { boost::poisson_distribution<> wordLenDist( meanLen ); boost::variate_generator< boost::mt19937&, boost::poisson_distribution<> > wordLenGen( rng, wordLenDist ); static int nSoFar = 0; static char letters[] = "abcdefghijklmnopqrstuvwxyz"; int len = wordLenGen(); std::string rv; rv.reserve( len ); for ( int i = 0; i < len; ++i ) rv.push_back( letters[ alphaIxGen() ] ); if ( ++nSoFar < 20 ) slog.debug() << __PRETTY_FUNCTION__ << ": generated '" << rv << "'"; return rv; } } // end namespace [anonymous] int main( int argc, char * argv [] ) { typedef Tony::SharedStringMap Map; const std::string shmName = "SharedMapTest"; Map map( shmName, 256 * 1024 ); if ( argc > 1 ) { std::string argv1( argv[1] ); if ( argv1 == "-c" ) { Map::removeMapping( shmName ); return 0; } } std::size_t nPairs = argc > 1 ? boost::lexical_cast< std::size_t >( argv[1] ) : 1000; std::size_t nReps = argc > 2 ? boost::lexical_cast< std::size_t >( argv[2] ) : 10; slog.info() << "nPairs=" << nPairs << ", nReps=" << nReps; std::vector< std::string > keys; std::vector< std::string > values; keys.reserve( nPairs ); keys.reserve( nPairs ); for ( int i = 0; i < nPairs; ++i ) { keys.push_back( genRandomString() ); values.push_back( genRandomString() ); } Tony::Stopwatch sw( Tony::Stopwatch::paused ); // ----------------------------------------------------------------- slog.info() << "timing individual inserts"; for ( int i = 0; i < nReps; ++i ) { Map::ShmStats stats; map.getShmStats( stats ); stats.dumpTo( slog.debug() << "before clear: " ); map.clear(); map.getShmStats( stats ); stats.dumpTo( slog.debug() << "after clear: " ); sw.start(); for ( int j = 0; j < nPairs; ++j ) { map.setOneValue( keys[j], values[j] ); } sw.pause(); map.getShmStats( stats ); stats.dumpTo( slog.debug() << "after load: " ); } slog.info() << boost::format( "done: %.3fs elapsed (%dns per rep, %dns per pair)" ) % sw.getElapsed() % sw.getNanosecondsPerIter( nReps ) % sw.getNanosecondsPerIter( nReps * nPairs ); // ----------------------------------------------------------------- sw.reset(); slog.info() << "timing bulk inserts (batch=" << nPairs / 4 << ")"; for ( int i = 0; i < nReps; ++i ) { Map::ShmStats stats; map.getShmStats( stats ); stats.dumpTo( slog.debug() << "before clear: " ); map.clear(); map.getShmStats( stats ); stats.dumpTo( slog.debug() << "after clear: " ); std::size_t nSkip = nPairs / 4; typedef Map::KeyVector::const_iterator ConstKeyIterator; ConstKeyIterator keysBegin( keys.begin() ); ConstKeyIterator keysEnd( keysBegin + nSkip ); typedef Map::ValueVector::const_iterator ConstValueIterator; ConstValueIterator valuesBegin( values.begin() ); sw.start(); for ( int j = 0; j < 4; ++j ) { map.setManyValues( keysBegin, keysEnd, valuesBegin ); keysBegin = keysEnd; keysEnd += nSkip; valuesBegin += nSkip; } sw.pause(); map.getShmStats( stats ); stats.dumpTo( slog.debug() << "after load: " ); } slog.info() << boost::format( "done: %.3fs elapsed (%dns per rep, %dns per pair)" ) % sw.getElapsed() % sw.getNanosecondsPerIter( nReps ) % sw.getNanosecondsPerIter( nReps * nPairs ); return 0; }