File: obbench.h

package info (click to toggle)
openbabel 2.4.1%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 58,308 kB
  • sloc: cpp: 459,210; ansic: 90,514; php: 13,963; python: 7,899; perl: 6,518; pascal: 793; sh: 179; xml: 97; ruby: 64; makefile: 46; java: 23; cs: 14
file content (152 lines) | stat: -rw-r--r-- 4,387 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#ifdef WIN32
  #include <Windows.h> // QueryPerformanceFrequency & QueryPerformanceCounter
#else
  #include <sys/timeb.h> // Linux and MacOSX
#endif

#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>

#include "obtest.h"

static bool headerWritten = false;

class BenchmarkLoop 
{
  public:
    BenchmarkLoop(const std::string &name = std::string())
    {
#ifdef WIN32
      QueryPerformanceFrequency(&m_frequency); // counts per second
#endif
      m_time = 0;
      m_loops = 0;
      m_start = getMilliCount();
      m_name = name;
    }
    ~BenchmarkLoop()
    {
      unsigned int milliSecsPerIter = m_time / m_loops;
      
      if (!m_name.empty()) {
        std::cout << "Benchmark: " << m_name << std::endl;

        // create header
        std::time_t now;
        std::time(&now);
        std::string dateStr = std::ctime(&now);
        if (dateStr[dateStr.size()-1] == '\n')
          dateStr = dateStr.substr(0, dateStr.size()-1);
        std::string header = "\"" + dateStr + "\"";

        // write time to a file so progress can be monitored
        std::ofstream ofs;
        ofs.open("benchmark.txt.new");
 
        // read the current benchmark.txt, update lines and write to .new file
        std::ifstream ifs;
        ifs.open("benchmark.txt");
        std::string line;
        bool foundBenchmark = false, foundHeader = false;
        if (headerWritten)
          foundHeader = true;
        while (std::getline(ifs, line)) {
          if (line.substr(0, 10) == "__Header__" && !headerWritten) {
            foundHeader = true;
            headerWritten = true;
            std::stringstream ss;
            ss << line << " " << header;
            line = ss.str();          
          }
          if (line.substr(0, m_name.size()) == m_name) {
            foundBenchmark = true;
            std::stringstream ss;
            ss << line << " " << milliSecsPerIter;
            line = ss.str();
          }
          
          ofs << line << std::endl;
        }
        ifs.close();
        ofs.close();

        if (!foundBenchmark) {
          // benchmark not found, append the new line
          ofs.open("benchmark.txt", std::ios::out | std::ios::app);
          if (!foundHeader)
            ofs << "__Header__ " << header << std::endl;
          ofs << m_name << " " << milliSecsPerIter << std::endl;
        } else {
          // benchmark found and updated .new file, copy it now
          ifs.open("benchmark.txt.new");
          ofs.open("benchmark.txt");
          if (!foundHeader)
            ofs << "__Header__" << header << std::endl;
          ofs << ifs.rdbuf();
        }
     }
      
      // print out in Xms, Xs or XmYs
      std::stringstream duration;
      if (milliSecsPerIter > 1000) {
        unsigned int secsPerIter = milliSecsPerIter / 1000;
        if (secsPerIter > 60) {
          unsigned int minutesPerIter = secsPerIter / 60;
          duration << minutesPerIter << "m" << secsPerIter % 60 << "s";        
        } else {
          duration << secsPerIter << "s";
        }
      } else {
        duration << milliSecsPerIter << "ms";
      }
      std::cout << duration.str() << " per iteration (" << m_loops << " iterations total)" << std::endl;
    }
    bool done()
    {
      if (m_time > 500) // iterate untill at least 500ms passed
        return true;
      return false;
    }
    void next()
    {
      m_time = getMilliSpan(m_start);
      ++m_loops;
    }
    unsigned int getMilliCount()
    {
#ifdef WIN32
      LARGE_INTEGER performanceCount;
      QueryPerformanceCounter(&performanceCount); // value in counts
      LARGE_INTEGER nCount = performanceCount / m_frequency * 1000;
      return nCount;
#else
      timeb tb;
      ftime( &tb );
      unsigned int nCount = tb.millitm + (tb.time & 0xfffff) * 1000;
      return nCount;
#endif
    }
    unsigned int getMilliSpan(unsigned int start)
    {
      int nSpan = getMilliCount() - start;
#ifndef WIN32
      if ( nSpan < 0 ) // handle overflow...
        nSpan += 0x100000 * 1000;
#endif
      return nSpan;
    }
  private:
    unsigned int m_time, m_start, m_loops;
    std::string m_name;
#ifdef WIN32
    LARGE_INTEGER m_frequency;
#endif
};

#define OB_BENCHMARK \
  for (BenchmarkLoop loop; !loop.done(); loop.next())

#define OB_NAMED_BENCHMARK(name) \
  for (BenchmarkLoop loop(#name); !loop.done(); loop.next())