Česky
Kamil Dudka

Share Library (C++)

File detail

Name:Downloadtest3_benchmark.cpp [Download]
Location: sharelib > src > test3
Size:7.4 KB
Last modification:2007-08-27 01:16

Source code

/**
 * @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;
}