source: src/Helpers/Chronos.cpp@ ca940b

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

FIX: Chronos is now working correctly, no more negative times.

  • extracted difference calculator into static function, making it thus accessible to unit testing.
  • kudos to Saskia Metzler for inspiring the test.
  • Property mode set to 100644
File size: 5.3 KB
RevLine 
[93abe8]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
[9b8fa4]20#include "CodePatterns/MemDebug.hpp"
[93abe8]21
22#include <iostream>
23
[760f97c]24#ifdef HAVE_UNISTD_H
25#include <unistd.h>
[8e24ef]26#ifdef HAVE_SYS_TIMES_H
27# include <sys/times.h>
28#else
29# include <time.h>
30#endif
[760f97c]31#else
32# include <time.h>
33#endif
34
[8e24ef]35
[9b8fa4]36#include "CodePatterns/Chronos.hpp"
[93abe8]37
[9b8fa4]38#include "CodePatterns/Singleton_impl.hpp"
[93abe8]39
40Chronos::Chronos()
[3f06bb]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}
[93abe8]57
58Chronos::~Chronos()
[3f06bb]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}
[93abe8]68
[3f06bb]69double Chronos::getTime(const std::string &_name) const
[93abe8]70{
71 // only those functions have a time that have run already
[3f06bb]72 if (AccountedTime.count(_name) != 0) {
[93abe8]73 // return -1 if function is currently running
[3f06bb]74 if (StartingTime.count(_name) == 0.)
[93abe8]75 return AccountedTime.at(_name);
76 else
[8e24ef]77 return -1.;
[93abe8]78 }
[8e24ef]79 return 0.;
[93abe8]80}
81
[3f06bb]82void Chronos::resetTime(const std::string &_name)
[93abe8]83{
[3f06bb]84 // set accounted time to zero
85 if (AccountedTime.count(_name) != 0) {
[8e24ef]86 AccountedTime[_name] = 0.;
[93abe8]87 }
[3f06bb]88 // and end if it's currently running
89 StartingTime.erase(_name);
90 RecursionMap.erase(_name);
[93abe8]91}
92
[3f06bb]93void Chronos::startTiming(const std::string &_name)
[93abe8]94{
95 // start time keeping
[3f06bb]96 if ((RecursionMap.count(_name) == 0) || (RecursionMap[_name] == 0)) {
97 StartingTime[_name] = getCurrentTime();
98 RecursionMap[_name] = 1;
99 } else {
100 ++RecursionMap[_name];
101 }
[8e24ef]102}
103
[ca940b]104double Chronos::calculateCorrectTimeDifference(
105 const sec_ncsec_t &_time1,
106 const sec_ncsec_t &_time2)
107{
108 double currenttime = 0.;
109 if (_time1.second < _time2.second)
110 currenttime = (_time1.first - _time2.first - 1)
111 + (1e9 + _time1.second - _time2.second) * 1.e-9;
112 else
113 currenttime = (_time1.first - _time2.first)
114 + (_time1.second - _time2.second) * 1.e-9;
115 return currenttime;
116}
117
[8e24ef]118double Chronos::getCurrentTime() const
119{
[3f06bb]120#ifdef HAVE_TIME_H
121 // clock_gettime gives nanoseconds accuracy
122 timespec time1;
123 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
[ca940b]124 double currenttime = calculateCorrectTimeDifference(
125 std::make_pair( time1.tv_sec, time1.tv_nsec),
126 std::make_pair( basetime.tv_sec, basetime.tv_nsec)
127 );
[3f06bb]128#else
129#ifdef HAVE_SYS_TIME_H
130 struct timezone timezone1;
131 timeval time1;
132 // gettimeofday gives microseconds accuracy
133 gettimeofday(&time1, &timezone1);
[ca940b]134 double currenttime = calculateCorrectTimeDifference(
135 std::make_pair( time1.tv_sec, time1.tv_usec),
136 std::make_pair( basetime.tv_sec, basetime.tv_usec)
137 );
[3f06bb]138#else
[8e24ef]139#ifdef HAVE_SYS_TIMES_H
[3f06bb]140 // clock is only accurate up to milliseconds
[8e24ef]141 struct tms *buffer = new tms;
142 if (times(buffer) != (clock_t)(-1))
[3f06bb]143 currenttime =
144 (double)(buffer->tms_utime - basetime->tms_utime)/(double)sysconf(_SC_CLK_TCK);
[8e24ef]145 else
146 currenttime = 0.;
147 delete buffer;
148#else
[3f06bb]149 // no time keeping possible
150 const double currenttime = 0.;
151#endif
152#endif
[8e24ef]153#endif
154 //std::cout << "Current time is " << currenttime << std::endl;
155 return currenttime;
[93abe8]156}
157
[3f06bb]158void Chronos::endTiming(const std::string &_name)
[93abe8]159{
[3f06bb]160 // check whether we are the topmost function, return if not
161 if (--RecursionMap[_name] != 0)
162 return;
[8e24ef]163
164 // if present
[3f06bb]165 ASSERT(StartingTime.count(_name), "Chronos::endTiming() - no timer under "
166 +_name+" running.");
167 ASSERT(RecursionMap.count(_name), "Chronos::endTiming() - negative recursion level for "
168 +_name+".");
169
[8e24ef]170 // finish time keeping
[3f06bb]171 const double endtime = getCurrentTime();
172 const double starttime = StartingTime[_name];
[8e24ef]173 const double RunTime = ((double)endtime - starttime);
[3f06bb]174 if (AccountedTime.count(_name) != 0)
[8e24ef]175 AccountedTime[_name] += RunTime;
176 else
177 AccountedTime[_name] = RunTime;
178
179 // and zero for next run
[3f06bb]180 StartingTime.erase(_name);
[93abe8]181}
182
[8e24ef]183double Chronos::SumUpTotalTime() const
[93abe8]184{
[8e24ef]185 double sum = 0.;
[93abe8]186 for (TimekeepingMap::const_iterator iter = AccountedTime.begin();
187 iter != AccountedTime.end();
188 ++iter) {
189 sum += iter->second;
190 }
191 return sum;
192}
193
194size_t Chronos::SumUpTotalFunctions() const
195{
[3f06bb]196 return AccountedTime.size();
[93abe8]197}
198
199std::ostream& operator<<(std::ostream &ost, const Chronos &_time)
200{
[8e24ef]201 ost << "List of functions present:" << std::endl;
202 for (Chronos::TimekeepingMap::const_iterator iter = _time.AccountedTime.begin();
203 iter != _time.AccountedTime.end();
204 ++iter)
205 ost << "\t" << iter->first << "\t" << iter->second << "s" << std::endl;
206 ost << "Total time passed: " << _time.SumUpTotalTime() << std::endl;
[93abe8]207 ost << "Total functions: " << _time.SumUpTotalFunctions() << std::endl;
208 return ost;
209}
210
[8e24ef]211// construct the remainder of the singleton
[93abe8]212CONSTRUCT_SINGLETON(Chronos)
[8e24ef]213
214// catch if someone wants to use Info objects in here
215#ifdef INFO_HPP_
216BOOST_PP_ASSERT_MSG(1,\
217 ERROR: This is a safety measure to generate a compiler warning\n \
218 if you really try to use info.hpp in __FILE__.)
219#endif
220
Note: See TracBrowser for help on using the repository browser.