1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 // vi: set et ts=8 sw=2 sts=2: 3 4 //make sure clock_gettime is available 5 #if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE < 199309L 6 #undef _POSIX_C_SOURCE 7 #endif 8 #if !defined(_POSIX_C_SOURCE) && !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__DragonFly__) 9 #define _POSIX_C_SOURCE 199309L 10 #endif 11 12 //make sure gettimeofday is available 13 #ifndef _DEFAULT_SOURCE 14 #define _DEFAULT_SOURCE 15 #endif 16 17 #if HAVE_CONFIG_H 18 #include "config.h" 19 #endif 20 21 #include <cerrno> 22 #include <iomanip> 23 #include <ostream> 24 #include <sstream> 25 #include <string> 26 27 #include <sys/resource.h> 28 #include <sys/time.h> 29 #include <time.h> 30 #include <unistd.h> 31 32 #include <dune/common/exceptions.hh> 33 34 #include "clock.hh" 35 36 namespace Dune { 37 namespace PDELab { 38 operator <<(std::ostream & s,const TimeSpec & t)39 std::ostream &operator<<(std::ostream &s, const TimeSpec &t) { 40 std::ostringstream tmp; 41 tmp << t.tv_sec << '.' << std::setfill('0') << std::setw(9) << t.tv_nsec; 42 std::string tmpstr = tmp.str(); 43 if(s.precision() < 9) 44 tmpstr.resize(tmpstr.size() - ( 9 - s.precision() )); 45 if(s.precision() == 0) 46 tmpstr.resize(tmpstr.size() - 1); 47 s << tmpstr; 48 return s; 49 } 50 51 ////////////////////////////////////////////////////////////////////// 52 // 53 // Wall time 54 // 55 56 #if HAVE_POSIX_CLOCK posixGetWallTime()57 TimeSpec posixGetWallTime() { 58 timespec result; 59 if(clock_gettime(CLOCK_REALTIME, &result) < 0) 60 DUNE_THROW(ClockError, "clock_gettime(CLOCK_REALTIME, ...) failed: " 61 "errno = " << errno); 62 TimeSpec tmp = { result.tv_sec, result.tv_nsec }; 63 return tmp; 64 } 65 posixGetWallTimeResolution()66 TimeSpec posixGetWallTimeResolution() { 67 timespec result; 68 if(clock_getres(CLOCK_REALTIME, &result) < 0) 69 DUNE_THROW(ClockError, "clock_getres(CLOCK_REALTIME, ...) failed: " 70 "errno = " << errno); 71 TimeSpec tmp = { result.tv_sec, result.tv_nsec }; 72 return tmp; 73 } 74 checkPOSIXGetWallTime()75 bool checkPOSIXGetWallTime() { 76 # if _POSIX_TIMERS == 0 77 return sysconf(_SC_TIMERS) > 0; 78 # else // _POSIX_TIMERS > 0 79 return true; 80 # endif // _POSIX_TIMERS > 0 81 } 82 #endif // HAVE_POSIX_CLOCK 83 gettimeofdayWallTime()84 TimeSpec gettimeofdayWallTime() { 85 timeval result; 86 if(gettimeofday(&result, NULL) < 0) 87 DUNE_THROW(ClockError, "gettimeofday() failed: errno = " << errno); 88 TimeSpec tmp = { result.tv_sec, 1000*result.tv_usec }; 89 return tmp; 90 } 91 gettimeofdayWallTimeResolution()92 const TimeSpec &gettimeofdayWallTimeResolution() { 93 static const TimeSpec res = { 0, 1000 }; 94 return res; 95 } 96 97 struct WallTimeClock { 98 TimeSpec (*clock)(); 99 TimeSpec resolution; 100 std::string clockName; 101 instanceDune::PDELab::WallTimeClock102 static const WallTimeClock &instance() { 103 static const WallTimeClock clock; 104 return clock; 105 } 106 107 private: WallTimeClockDune::PDELab::WallTimeClock108 WallTimeClock() { 109 #if HAVE_POSIX_CLOCK 110 if(checkPOSIXGetWallTime()) { 111 clock = posixGetWallTime; 112 resolution = posixGetWallTimeResolution(); 113 clockName = "clock_gettime(CLOCK_REALTIME, ...)"; 114 return; 115 } 116 #endif // HAVE_POSIX_CLOCK 117 { 118 clock = gettimeofdayWallTime; 119 resolution = gettimeofdayWallTimeResolution(); 120 clockName = "gettimeofday(...)"; 121 return; 122 } 123 } 124 }; getWallTime()125 TimeSpec getWallTime() { return WallTimeClock::instance().clock(); } getWallTimeResolution()126 TimeSpec getWallTimeResolution() 127 { return WallTimeClock::instance().resolution; } getWallTimeImp()128 const std::string &getWallTimeImp() 129 { return WallTimeClock::instance().clockName; } 130 131 ////////////////////////////////////////////////////////////////////// 132 // 133 // Process Time 134 // 135 136 #if HAVE_POSIX_CLOCK && _POSIX_CPUTIME >= 0 posixGetProcessTime()137 TimeSpec posixGetProcessTime() { 138 // Use clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) even though that may 139 // be problematic in the context of process migration between cores. In 140 // practice, it appears to still be far better then the next best 141 // alternative, getrusage(), which will only update the clock every 142 // jiffy. 143 timespec result; 144 if(clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &result) < 0) 145 DUNE_THROW(ClockError, "clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) " 146 "failed: errno = " << errno); 147 TimeSpec tmp = { result.tv_sec, result.tv_nsec }; 148 return tmp; 149 } 150 posixGetProcessTimeResolution()151 TimeSpec posixGetProcessTimeResolution() { 152 timespec result; 153 if(clock_getres(CLOCK_PROCESS_CPUTIME_ID, &result) < 0) 154 DUNE_THROW(ClockError, "clock_getres(CLOCK_PROCESS_CPUTIME_ID, ...) " 155 "failed: errno = " << errno); 156 TimeSpec tmp = { result.tv_sec, result.tv_nsec }; 157 return tmp; 158 } 159 checkPOSIXGetProcessTime()160 bool checkPOSIXGetProcessTime() { 161 # if _POSIX_CPUTIME == 0 162 return sysconf(_SC_CPUTIME) > 0; 163 # else // _POSIX_CPUTIME > 0 164 return true; 165 # endif // _POSIX_CPUTIME > 0 166 } 167 #endif // HAVE_POSIX_CLOCK && _POSIX_CPUTIME >= 0 168 getrusageProcessTime()169 TimeSpec getrusageProcessTime() { 170 rusage ru; 171 if(getrusage(RUSAGE_SELF, &ru) < 0) 172 DUNE_THROW(ClockError, "getrusage(RUSAGE_SELF, ...) failed: errno = " 173 << errno); 174 TimeSpec time = { ru.ru_utime.tv_sec, 1000*ru.ru_utime.tv_usec }; 175 TimeSpec tmp = { ru.ru_stime.tv_sec, 1000*ru.ru_stime.tv_usec }; 176 time += tmp; 177 return time; 178 } 179 getrusageProcessTimeResolution()180 const TimeSpec &getrusageProcessTimeResolution() { 181 static const TimeSpec res = { 0, 1000 }; 182 return res; 183 } 184 185 struct ProcessTimeClock { 186 TimeSpec (*clock)(); 187 TimeSpec resolution; 188 std::string clockName; 189 instanceDune::PDELab::ProcessTimeClock190 static const ProcessTimeClock &instance() { 191 static const ProcessTimeClock clock; 192 return clock; 193 } 194 195 private: ProcessTimeClockDune::PDELab::ProcessTimeClock196 ProcessTimeClock() { 197 #if HAVE_POSIX_CLOCK && _POSIX_CPUTIME >= 0 198 if(checkPOSIXGetProcessTime()) 199 { 200 clock = posixGetProcessTime; 201 resolution = posixGetProcessTimeResolution(); 202 clockName = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)"; 203 return; 204 } 205 #endif // HAVE_POSIX_CLOCK && _POSIX_CPUTIME 206 { 207 clock = getrusageProcessTime; 208 resolution = getrusageProcessTimeResolution(); 209 clockName = "getrusage(RUSAGE_SELF, ...)"; 210 } 211 } 212 }; getProcessTime()213 TimeSpec getProcessTime() { return ProcessTimeClock::instance().clock(); } getProcessTimeResolution()214 TimeSpec getProcessTimeResolution() 215 { return ProcessTimeClock::instance().resolution; } getProcessTimeImp()216 const std::string &getProcessTimeImp() 217 { return ProcessTimeClock::instance().clockName; } 218 219 } // namespace PDELab 220 } // namespace Dune 221