/**
* @file test3_benchmark.cpp
* @brief Share library - test3 (WordCount benchmark)
* @author Kamil Dudka, xdudka00@gmail.com
* @date 2007-05-15
*/
#include "sharelib.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>
#include <time.h>
using Share::ShareManager;
/**
* [Linux]
* Please, increase /proc/sys/kernel/shm*, if shmget() fails
*/
const size_t SharedSegmentSize = 196 * 1024 * 1024;
/**
* Wrapper around clock() from time.h
*/
class StopWatchCore {
public:
void start();
double stop();
private:
clock_t stamp_;
};
/**
* StopWatch using std::cout to display statistics
*/
class StopWatch {
public:
void start(const char *message);
void stop();
private:
StopWatchCore core_;
};
/**
* WordCount from test2_wordcount as template
*/
template <
class TString,
class TMap
>
class WordCount: public Share::SharedObject {
public:
WordCount()/*: hashTable_(htSize)*/ { }
void parse (const char *);
private:
TMap hashTable_;
};
/**
* Allocate WordCount statically
* and parse file
*/
template <class TWordCount>
void wcParseStatic (const char *fileName)
{
TWordCount wcStatic;
wcStatic.parse (fileName);
}
/**
* Allocate WordCount dynamically
* and parse file
*/
template <class TWordCount>
void wcParseDynamic (const char *fileName)
{
TWordCount *wcDynamic = new TWordCount;
wcDynamic-> parse (fileName);
delete wcDynamic;
}
// argc==1: Print usage
// argc==2: Parse file given as argument
int main (int argc, char *argv[])
{
try {
switch (argc) {
default:
std::cout <<
"Usage:\n"
" test3_benchmark FILE_TO_PARSE\n";
return 1;
case 2:
break;
}
// test 0
typedef WordCount <std::string, std::map<std::string, int> > TWordCount0;
// test 1
typedef std::basic_string <char, std::char_traits<char>, Share::Allocator<char> > TString1;
typedef std::map <TString1, int, std::less <const TString1>, Share::Allocator<std::pair <const TString1, int> > > TMap1;
typedef WordCount <TString1, TMap1> TWordCount1;
// test 2
typedef WordCount <std::string, Share::Map<std::string, int> > TWordCount2;
// test 3
typedef TString1 TString3;
typedef Share::Map <TString3, int, Share::Allocator<Share::Pair <const TString3, int> > > TMap3;
typedef WordCount <TString3, TMap3> TWordCount3;
// test 4
typedef Share::String<std::allocator <char> > TString4;
typedef WordCount <TString4, std::map<TString4, int> > TWordCount4;
// test 5
typedef Share::String <Share::Allocator<char> > TString5;
typedef std::map <TString5, int, std::less <const TString5>, Share::Allocator<std::pair <const TString5, int> > > TMap5;
typedef WordCount <TString5, TMap5> TWordCount5;
// test 6
typedef Share::String <std::allocator <char> > TString6;
typedef WordCount <TString6, Share::Map<TString6, int> > TWordCount6;
// test 7
typedef TString5 TString7;
typedef Share::Map <TString7, int, Share::Allocator<Share::Pair <const TString7, int> > > TMap7;
typedef WordCount <TString7, TMap7> TWordCount7;
// stage enumeration
typedef enum {
STAGE_STATIC = 0,
STAGE_DYNAMIC,
STAGE_SHARED
} EStage;
const char *stageNames[] = {
"Static allocation (stage 1 of 3)", // STAGE_STATIC
"Dynamic allocation (stage 2 of 3)", // STAGE_DYNAMIC
"Allocation inside shared segment (stage 3 of 3)" // STAGE_SHARED
};
const char *testNames[] = {
" std::string, std::map, std::allocator (test 1 of 8)", // test 0
" std::string, std::map, Share::Allocator (test 2 of 8)", // test 1
" std::string, Share::Map, std::allocator (test 3 of 8)", // test 2
" std::string, Share::Map, Share::Allocator (test 4 of 8)", // test 3
"Share::String, std::map, std::allocator (test 5 of 8)", // test 4
"Share::String, std::map, Share::Allocator (test 6 of 8)", // test 5
"Share::String, Share::Map, std::allocator (test 7 of 8)", // test 6
"Share::String, Share::Map, Share::Allocator (test 8 of 8)" // test 7
};
// stop watch local instance
StopWatch stopWatch;
// ShareManager singleton instance
ShareManager *manager = ShareManager::instance();
// stage loop
for (int stage=0; stage<3; stage++) {
std::cout << stageNames [stage] << std::endl;
if (stage==STAGE_SHARED) {
// Allocate shared segment
manager-> createSegment("test3_benchmark", SharedSegmentSize);
manager-> unlinkSegment();
}
// test loop
for (int test=0; test<8; test++) {
stopWatch.start (testNames[test]);
switch (stage) {
case STAGE_STATIC:
switch (test) {
case 0: wcParseStatic<TWordCount0> (argv[1]); break;
case 1: wcParseStatic<TWordCount1> (argv[1]); break;
case 2: wcParseStatic<TWordCount2> (argv[1]); break;
case 3: wcParseStatic<TWordCount3> (argv[1]); break;
case 4: wcParseStatic<TWordCount4> (argv[1]); break;
case 5: wcParseStatic<TWordCount5> (argv[1]); break;
case 6: wcParseStatic<TWordCount6> (argv[1]); break;
case 7: wcParseStatic<TWordCount7> (argv[1]); break;
}
case STAGE_DYNAMIC:
case STAGE_SHARED:
switch (test) {
case 0: wcParseDynamic<TWordCount0> (argv[1]); break;
case 1: wcParseDynamic<TWordCount1> (argv[1]); break;
case 2: wcParseDynamic<TWordCount2> (argv[1]); break;
case 3: wcParseDynamic<TWordCount3> (argv[1]); break;
case 4: wcParseDynamic<TWordCount4> (argv[1]); break;
case 5: wcParseDynamic<TWordCount5> (argv[1]); break;
case 6: wcParseDynamic<TWordCount6> (argv[1]); break;
case 7: wcParseDynamic<TWordCount7> (argv[1]); break;
}
}
stopWatch.stop();
} // (test loop)
if (stage==STAGE_SHARED)
// destroy shared segment
manager-> detachSegment();
std::cout << std::endl;
} // (stage loop)
}
catch (Share::ShareException e) {
// error handling
ShareManager::instance()-> detachSegment();
std::cerr << "test3_benchmark: " << e.message() << std::endl;
}
}
template <
class TString,
class TMap
>
void WordCount<TString, TMap>::parse (const char *fileName)
{
class OpenedFileRAII {
std::ifstream fin_;
public:
OpenedFileRAII (const char *fileName): fin_ (fileName) { }
~OpenedFileRAII() { fin_.close(); }
operator std::ifstream &() { return fin_; }
operator bool() { return fin_; }
} fin (fileName);
if (!fin) {
std::ostringstream stream;
stream << "Unable to read file " << fileName;
throw Share::ShareException (stream.str().c_str());
}
for (std::string word; static_cast<std::ifstream &>(fin) >> word; ) {
TString str (word.c_str());
hashTable_ [str] ++;
}
}
void StopWatchCore::start()
{
stamp_ = clock();
}
double StopWatchCore::stop()
{
clock_t diff = clock() - stamp_;
return static_cast<double>(diff)/CLOCKS_PER_SEC;
}
void StopWatch::start (const char *message)
{
std::cout << " " << message << ": " << std::flush;
core_.start();
}
void StopWatch::stop()
{
std::cout << core_.stop() << " s" << std::endl;
}