/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * Chronos.cpp * * Created on: Mar 14, 2011 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif //#include "CodePatterns/MemDebug.hpp" #include #ifdef HAVE_UNISTD_H #include #ifdef HAVE_SYS_TIMES_H # include #else # include #endif #else # include #endif #include "CodePatterns/Chronos.hpp" #include "CodePatterns/Singleton_impl.hpp" Chronos::Chronos() { // get time and store it internally as base time #ifdef HAVE_TIME_H clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &basetime); #else #ifdef HAVE_SYS_TIME_H struct timezone timezone1; gettimeofday(&basetime, &timezone1); #else #ifdef HAVE_SYS_TIMES_H struct tms *basetime = new tms; times(basetime); #endif #endif #endif } Chronos::~Chronos() { #ifndef HAVE_TIME_H #ifndef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIMES_H delete basetime; #endif #endif #endif } double Chronos::getTime(const std::string &_name) const { // only those functions have a time that have run already if (AccountedTime.count(_name) != 0) { // return -1 if function is currently running if (StartingTime.count(_name) == 0.) return AccountedTime.at(_name); else return -1.; } return 0.; } void Chronos::resetTime(const std::string &_name) { // set accounted time to zero if (AccountedTime.count(_name) != 0) { AccountedTime[_name] = 0.; } // and end if it's currently running StartingTime.erase(_name); RecursionMap.erase(_name); } void Chronos::startTiming(const std::string &_name) { // start time keeping if ((RecursionMap.count(_name) == 0) || (RecursionMap[_name] == 0)) { StartingTime[_name] = getCurrentTime(); RecursionMap[_name] = 1; } else { ++RecursionMap[_name]; } } double Chronos::calculateCorrectTimeDifference( const sec_ncsec_t &_time1, const sec_ncsec_t &_time2) { double currenttime = 0.; if (_time1.second < _time2.second) currenttime = (_time1.first - _time2.first - 1) + (1e9 + _time1.second - _time2.second) * 1.e-9; else currenttime = (_time1.first - _time2.first) + (_time1.second - _time2.second) * 1.e-9; return currenttime; } double Chronos::getCurrentTime() const { #ifdef HAVE_TIME_H // clock_gettime gives nanoseconds accuracy timespec time1; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1); double currenttime = calculateCorrectTimeDifference( std::make_pair( time1.tv_sec, time1.tv_nsec), std::make_pair( basetime.tv_sec, basetime.tv_nsec) ); #else #ifdef HAVE_SYS_TIME_H struct timezone timezone1; timeval time1; // gettimeofday gives microseconds accuracy gettimeofday(&time1, &timezone1); double currenttime = calculateCorrectTimeDifference( std::make_pair( time1.tv_sec, time1.tv_usec), std::make_pair( basetime.tv_sec, basetime.tv_usec) ); #else #ifdef HAVE_SYS_TIMES_H // clock is only accurate up to milliseconds struct tms *buffer = new tms; if (times(buffer) != (clock_t)(-1)) currenttime = (double)(buffer->tms_utime - basetime->tms_utime)/(double)sysconf(_SC_CLK_TCK); else currenttime = 0.; delete buffer; #else // no time keeping possible const double currenttime = 0.; #endif #endif #endif //std::cout << "Current time is " << currenttime << std::endl; return currenttime; } void Chronos::endTiming(const std::string &_name) { // check whether we are the topmost function, return if not if (--RecursionMap[_name] != 0) return; // if present ASSERT(StartingTime.count(_name), "Chronos::endTiming() - no timer under " +_name+" running."); ASSERT(RecursionMap.count(_name), "Chronos::endTiming() - negative recursion level for " +_name+"."); // finish time keeping const double endtime = getCurrentTime(); const double starttime = StartingTime[_name]; const double RunTime = ((double)endtime - starttime); if (AccountedTime.count(_name) != 0) AccountedTime[_name] += RunTime; else AccountedTime[_name] = RunTime; // and zero for next run StartingTime.erase(_name); } double Chronos::SumUpTotalTime() const { double sum = 0.; for (TimekeepingMap::const_iterator iter = AccountedTime.begin(); iter != AccountedTime.end(); ++iter) { sum += iter->second; } return sum; } size_t Chronos::SumUpTotalFunctions() const { return AccountedTime.size(); } std::ostream& operator<<(std::ostream &ost, const Chronos &_time) { ost << "List of functions present:" << std::endl; for (Chronos::TimekeepingMap::const_iterator iter = _time.AccountedTime.begin(); iter != _time.AccountedTime.end(); ++iter) ost << "\t" << iter->first << "\t" << iter->second << "s" << std::endl; ost << "Total time passed: " << _time.SumUpTotalTime() << std::endl; ost << "Total functions: " << _time.SumUpTotalFunctions() << std::endl; return ost; } // construct the remainder of the singleton CONSTRUCT_SINGLETON(Chronos) // catch if someone wants to use Info objects in here #ifdef INFO_HPP_ BOOST_PP_ASSERT_MSG(1,\ ERROR: This is a safety measure to generate a compiler warning\n \ if you really try to use info.hpp in __FILE__.) #endif