source: src/Helpers/Chronos.cpp@ 3f06bb

Last change on this file since 3f06bb was 3f06bb, checked in by Frederik Heber <heber@…>, 13 years ago

Enhanced Chronos for more accurate timekeeping.

  • Chronos is now safe to use w.r.t. recursive function calls.
  • Chronos now gets const ref of token name in each function.
  • TESTFIX: dummyTest() now checks on recursive function.
  • Chronos now offers its internal timekeeping via const ref to outside.
  • Chronos also now has up to nanoseconds precision when either time.h or sys/time.h is present.
  • librt required from clock_gettime().
  • Property mode set to 100644
File size: 5.1 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * Chronos.cpp
10 *
11 * Created on: Mar 14, 2011
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include "CodePatterns/MemDebug.hpp"
21
22#include <iostream>
23
24#ifdef HAVE_UNISTD_H
25#include <unistd.h>
26#ifdef HAVE_SYS_TIMES_H
27# include <sys/times.h>
28#else
29# include <time.h>
30#endif
31#else
32# include <time.h>
33#endif
34
35
36#include "CodePatterns/Chronos.hpp"
37
38#include "CodePatterns/Singleton_impl.hpp"
39
40Chronos::Chronos()
41{
42 // get time and store it internally as base time
43#ifdef HAVE_TIME_H
44 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &basetime);
45#else
46#ifdef HAVE_SYS_TIME_H
47 struct timezone timezone1;
48 gettimeofday(&basetime, &timezone1);
49#else
50#ifdef HAVE_SYS_TIMES_H
51 struct tms *basetime = new tms;
52 times(basetime);
53#endif
54#endif
55#endif
56}
57
58Chronos::~Chronos()
59{
60#ifndef HAVE_TIME_H
61#ifndef HAVE_SYS_TIME_H
62#ifdef HAVE_SYS_TIMES_H
63 delete basetime;
64#endif
65#endif
66#endif
67}
68
69double Chronos::getTime(const std::string &_name) const
70{
71 // only those functions have a time that have run already
72 if (AccountedTime.count(_name) != 0) {
73 // return -1 if function is currently running
74 if (StartingTime.count(_name) == 0.)
75 return AccountedTime.at(_name);
76 else
77 return -1.;
78 }
79 return 0.;
80}
81
82void Chronos::resetTime(const std::string &_name)
83{
84 // set accounted time to zero
85 if (AccountedTime.count(_name) != 0) {
86 AccountedTime[_name] = 0.;
87 }
88 // and end if it's currently running
89 StartingTime.erase(_name);
90 RecursionMap.erase(_name);
91}
92
93void Chronos::startTiming(const std::string &_name)
94{
95 // start time keeping
96 if ((RecursionMap.count(_name) == 0) || (RecursionMap[_name] == 0)) {
97 StartingTime[_name] = getCurrentTime();
98 RecursionMap[_name] = 1;
99 } else {
100 ++RecursionMap[_name];
101 }
102}
103
104double Chronos::getCurrentTime() const
105{
106#ifdef HAVE_TIME_H
107 // clock_gettime gives nanoseconds accuracy
108 timespec time1;
109 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
110 double currenttime;
111 if (time1.tv_nsec < basetime.tv_nsec)
112 currenttime = (time1.tv_sec - basetime.tv_sec - 1)
113 + (basetime.tv_nsec - time1.tv_nsec) * 1.e-9;
114 else
115 currenttime = (time1.tv_sec - basetime.tv_sec)
116 + (time1.tv_nsec - basetime.tv_nsec) * 1.e-9;
117#else
118#ifdef HAVE_SYS_TIME_H
119 struct timezone timezone1;
120 timeval time1;
121 // gettimeofday gives microseconds accuracy
122 gettimeofday(&time1, &timezone1);
123 double currenttime;
124 if (time1.tv_usec < basetime.tv_usec)
125 currenttime = (time1.tv_sec - basetime.tv_sec - 1)
126 + (basetime.tv_usec - time1.tv_usec) * 1.e-6;
127 else
128 currenttime = (time1.tv_sec - basetime.tv_sec)
129 + (time1.tv_usec - basetime.tv_usec) * 1.e-6;
130#else
131#ifdef HAVE_SYS_TIMES_H
132 // clock is only accurate up to milliseconds
133 struct tms *buffer = new tms;
134 double currenttime;
135 if (times(buffer) != (clock_t)(-1))
136 currenttime =
137 (double)(buffer->tms_utime - basetime->tms_utime)/(double)sysconf(_SC_CLK_TCK);
138 else
139 currenttime = 0.;
140 delete buffer;
141#else
142 // no time keeping possible
143 const double currenttime = 0.;
144#endif
145#endif
146#endif
147 //std::cout << "Current time is " << currenttime << std::endl;
148 return currenttime;
149}
150
151void Chronos::endTiming(const std::string &_name)
152{
153 // check whether we are the topmost function, return if not
154 if (--RecursionMap[_name] != 0)
155 return;
156
157 // if present
158 ASSERT(StartingTime.count(_name), "Chronos::endTiming() - no timer under "
159 +_name+" running.");
160 ASSERT(RecursionMap.count(_name), "Chronos::endTiming() - negative recursion level for "
161 +_name+".");
162
163 // finish time keeping
164 const double endtime = getCurrentTime();
165 const double starttime = StartingTime[_name];
166 const double RunTime = ((double)endtime - starttime);
167 if (AccountedTime.count(_name) != 0)
168 AccountedTime[_name] += RunTime;
169 else
170 AccountedTime[_name] = RunTime;
171
172 // and zero for next run
173 StartingTime.erase(_name);
174}
175
176double Chronos::SumUpTotalTime() const
177{
178 double sum = 0.;
179 for (TimekeepingMap::const_iterator iter = AccountedTime.begin();
180 iter != AccountedTime.end();
181 ++iter) {
182 sum += iter->second;
183 }
184 return sum;
185}
186
187size_t Chronos::SumUpTotalFunctions() const
188{
189 return AccountedTime.size();
190}
191
192std::ostream& operator<<(std::ostream &ost, const Chronos &_time)
193{
194 ost << "List of functions present:" << std::endl;
195 for (Chronos::TimekeepingMap::const_iterator iter = _time.AccountedTime.begin();
196 iter != _time.AccountedTime.end();
197 ++iter)
198 ost << "\t" << iter->first << "\t" << iter->second << "s" << std::endl;
199 ost << "Total time passed: " << _time.SumUpTotalTime() << std::endl;
200 ost << "Total functions: " << _time.SumUpTotalFunctions() << std::endl;
201 return ost;
202}
203
204// construct the remainder of the singleton
205CONSTRUCT_SINGLETON(Chronos)
206
207// catch if someone wants to use Info objects in here
208#ifdef INFO_HPP_
209BOOST_PP_ASSERT_MSG(1,\
210 ERROR: This is a safety measure to generate a compiler warning\n \
211 if you really try to use info.hpp in __FILE__.)
212#endif
213
Note: See TracBrowser for help on using the repository browser.