klee
Time.cpp
Go to the documentation of this file.
1//===-- Time.cpp ----------------------------------------------------------===//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
11#include "klee/System/Time.h"
12
13
14#include <cstdint>
15#include <regex>
16#include <sstream>
17#include <tuple>
18#include <sys/resource.h>
19
20
21using namespace klee;
22
23
24/* Why std::chrono:
25 * - C++11
26 * - separation between time points and durations
27 * - good performance on Linux and macOS (similar to gettimeofday)
28 * and not:
29 * - clock_gettime(CLOCK_MONOTONIC_COARSE): software clock, Linux-specific
30 * - clock_gettime(CLOCK_MONOTONIC): slowest on macOS, C-like API
31 * - gettimeofday: C-like API, non-monotonic
32 *
33 * TODO: add time literals with C++14
34 */
35
36// === Point ===
37
38// operators
39time::Point& time::Point::operator+=(const time::Span &span) { point += span.duration; return *this; }
40time::Point& time::Point::operator-=(const time::Span &span) { point -= span.duration; return *this; }
41
42time::Point time::operator+(const time::Point &point, const time::Span &span) { return time::Point(point.point + span.duration); }
43time::Point time::operator+(const time::Span &span, const time::Point &point) { return time::Point(point.point + span.duration); }
44time::Point time::operator-(const time::Point &point, const time::Span &span) { return time::Point(point.point - span.duration); }
45time::Span time::operator-(const time::Point &lhs, const time::Point &rhs) { return time::Span(lhs.point - rhs.point); }
46bool time::operator==(const time::Point &lhs, const time::Point &rhs) { return lhs.point == rhs.point; }
47bool time::operator!=(const time::Point &lhs, const time::Point &rhs) { return lhs.point != rhs.point; }
48bool time::operator<(const time::Point &lhs, const time::Point &rhs) { return lhs.point < rhs.point; }
49bool time::operator<=(const time::Point &lhs, const time::Point &rhs) { return lhs.point <= rhs.point; }
50bool time::operator>(const time::Point &lhs, const time::Point &rhs) { return lhs.point > rhs.point; }
51bool time::operator>=(const time::Point &lhs, const time::Point &rhs) { return lhs.point >= rhs.point; }
52
53
54// === Span ===
55
56// ctors
58time::Span::Span(const std::string &s) {
59 if (s.empty()) return;
60
61 std::regex re("^([0-9]*\\.?[0-9]+)|((([0-9]+)(h|min|s|ms|us|ns))+)$", std::regex::extended);
62 std::regex nre("([0-9]+)(h|min|s|ms|us|ns)", std::regex::extended);
63 std::smatch match;
64 std::string submatch;
65
66 // error
67 if (!std::regex_match(s, match, re)) goto error;
68
69 // old (double) format
70 submatch = match[1].str();
71 if (match[1].matched) {
72 errno = 0;
73 auto value = std::stod(submatch);
74 if (errno) goto error;
75
76 std::chrono::duration<double> d(value);
77 duration = std::chrono::duration_cast<std::chrono::microseconds>(d);
78 }
79
80 // new (string) format
81 submatch = match[2].str();
82 for (std::smatch m; std::regex_search(submatch, m, nre); submatch = m.suffix()) {
83 errno = 0;
84 const auto value = std::stoull(m[1]);
85 if (errno) goto error;
86
87 Duration d;
88 if (m[2] == "h") d = std::chrono::hours(value);
89 else if (m[2] == "min") d = std::chrono::minutes(value);
90 else if (m[2] == "s") d = std::chrono::seconds(value);
91 else if (m[2] == "ms") d = std::chrono::milliseconds(value);
92 else if (m[2] == "us") d = std::chrono::microseconds(value);
93 else if (m[2] == "ns") d = std::chrono::nanoseconds(value);
94 else goto error;
95
96 duration += d;
97 }
98
99 return;
100
101error:
102 klee_error("Illegal number format: %s", s.c_str());
103}
104
105// operators
106time::Span& time::Span::operator=(const time::Duration &d) { duration = d; return *this; };
107time::Span& time::Span::operator+=(const time::Span &other) { duration += other.duration; return *this; }
108time::Span& time::Span::operator-=(const time::Span &other) { duration -= other.duration; return *this; }
109time::Span& time::Span::operator*=(unsigned factor) { duration *= factor; return *this; }
111 duration = std::chrono::microseconds((std::uint64_t)((double)toMicroseconds() * factor));
112 return *this;
113}
114
115time::Span time::operator+(const time::Span &lhs, const time::Span &rhs) { return time::Span(lhs.duration + rhs.duration); }
116time::Span time::operator-(const time::Span &lhs, const time::Span &rhs) { return time::Span(lhs.duration - rhs.duration); }
117time::Span time::operator*(const time::Span &span, double factor) {
118 return time::Span(std::chrono::microseconds((std::uint64_t)((double)span.toMicroseconds() * factor)));
119};
120time::Span time::operator*(double factor, const time::Span &span) {
121 return time::Span(std::chrono::microseconds((std::uint64_t)((double)span.toMicroseconds() * factor)));
122};
123time::Span time::operator*(const time::Span &span, unsigned factor) { return time::Span(span.duration * factor); }
124time::Span time::operator*(unsigned factor, const time::Span &span) { return time::Span(span.duration * factor); }
125time::Span time::operator/(const time::Span &span, unsigned divisor) { return time::Span(span.duration / divisor); }
126bool time::operator==(const time::Span &lhs, const time::Span &rhs) { return lhs.duration == rhs.duration; }
127bool time::operator<=(const time::Span &lhs, const time::Span &rhs) { return lhs.duration <= rhs.duration; }
128bool time::operator>=(const time::Span &lhs, const time::Span &rhs) { return lhs.duration >= rhs.duration; }
129bool time::operator<(const time::Span &lhs, const time::Span &rhs) { return lhs.duration < rhs.duration; }
130bool time::operator>(const time::Span &lhs, const time::Span &rhs) { return lhs.duration > rhs.duration; }
131
132std::ostream& time::operator<<(std::ostream &stream, time::Span span) { return stream << span.toSeconds() << 's'; }
133llvm::raw_ostream& time::operator<<(llvm::raw_ostream &stream, time::Span span) { return stream << span.toSeconds() << 's'; }
134
135
136// units
137time::Span time::hours(std::uint16_t ticks) { return time::Span(std::chrono::hours(ticks)); }
138time::Span time::minutes(std::uint16_t ticks) { return time::Span(std::chrono::minutes(ticks)); }
139time::Span time::seconds(std::uint64_t ticks) { return time::Span(std::chrono::seconds(ticks)); }
142time::Span time::nanoseconds(std::uint64_t ticks) { return time::Span(std::chrono::nanoseconds(ticks)); }
143
144
145// conversions
146time::Span::operator time::Duration() const { return duration; }
147
148time::Span::operator bool() const { return duration.count() != 0; }
149
150time::Span::operator timeval() const {
151 timeval tv{};
152 const auto secs = std::chrono::duration_cast<std::chrono::seconds>(duration);
153 const auto usecs = std::chrono::duration_cast<std::chrono::microseconds>(duration - secs);
154 tv.tv_sec = secs.count();
155 tv.tv_usec = usecs.count();
156 return tv;
157}
158
159std::uint64_t time::Span::toMicroseconds() const {
160 return (std::uint64_t)std::chrono::duration_cast<std::chrono::microseconds>(duration).count();
161}
162
163double time::Span::toSeconds() const {
164 return std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() / (double)1000000000;
165}
166
167std::tuple<std::uint32_t, std::uint8_t, std::uint8_t> time::Span::toHMS() const {
168 auto d = duration;
169 const auto h = std::chrono::duration_cast<std::chrono::hours>(d);
170 const auto m = std::chrono::duration_cast<std::chrono::minutes>(d -= h);
171 const auto s = std::chrono::duration_cast<std::chrono::seconds>(d -= m);
172
173 return std::make_tuple((std::uint32_t) h.count(), (std::uint8_t) m.count(), (std::uint8_t) s.count());
174}
175
176
177// methods
179std::string time::getClockInfo() {
180 std::stringstream buffer;
181 buffer << "Using monotonic steady clock with "
182 << std::chrono::steady_clock::period::num
183 << '/'
184 << std::chrono::steady_clock::period::den
185 << "s resolution\n";
186 return buffer.str();
187}
188
189
192 rusage usage{};
193 auto ret = ::getrusage(RUSAGE_SELF, &usage);
194
195 if (ret) {
196 klee_warning("getrusage returned with error, return (0,0)");
197 return {};
198 } else {
199 return time::seconds(static_cast<std::uint64_t>(usage.ru_utime.tv_sec)) +
200 time::microseconds(static_cast<std::uint64_t>(usage.ru_utime.tv_usec));
201 }
202}
203
204
207 return time::Point(std::chrono::steady_clock::now());
208}
209
static void usage(void)
Definition: klee-replay.c:269
bool operator>(const Point &, const Point &)
Definition: Time.cpp:50
Span microseconds(std::uint64_t)
Definition: Time.cpp:141
Point operator+(const Point &, const Span &)
Definition: Time.cpp:42
Span getUserTime()
Returns time spent by this process in user mode.
Definition: Time.cpp:191
Span nanoseconds(std::uint64_t)
Definition: Time.cpp:142
Span minutes(std::uint16_t)
Definition: Time.cpp:138
Span operator/(const Span &, unsigned)
Definition: Time.cpp:125
Span hours(std::uint16_t)
time spans
Definition: Time.cpp:137
Point getWallTime()
Returns point in time using a monotonic steady clock.
Definition: Time.cpp:206
bool operator>=(const Point &, const Point &)
Definition: Time.cpp:51
Span operator*(const Span &, double)
Definition: Time.cpp:117
std::string getClockInfo()
Returns information about clock.
Definition: Time.cpp:179
bool operator<=(const Point &, const Point &)
Definition: Time.cpp:49
bool operator==(const Point &, const Point &)
Definition: Time.cpp:46
Span seconds(std::uint64_t)
Definition: Time.cpp:139
Span milliseconds(std::uint64_t)
Definition: Time.cpp:140
bool operator!=(const Point &, const Point &)
Definition: Time.cpp:47
bool operator<(const Point &, const Point &)
Definition: Time.cpp:48
std::ostream & operator<<(std::ostream &, Span)
Span -> "X.Ys".
Definition: Time.cpp:132
Point operator-(const Point &, const Span &)
Definition: Time.cpp:44
Definition: main.cpp:291
void klee_error(const char *msg,...) __attribute__((format(printf
void void void klee_warning(const char *msg,...) __attribute__((format(printf
Point & operator-=(const Span &)
Definition: Time.cpp:40
SteadyTimePoint point
Definition: Time.h:42
double toSeconds() const
Definition: Time.cpp:163
std::tuple< std::uint32_t, std::uint8_t, std::uint8_t > toHMS() const
Definition: Time.cpp:167
std::uint64_t toMicroseconds() const
Definition: Time.cpp:159
Span & operator*=(unsigned)
Definition: Time.cpp:109
Duration duration
Definition: Time.h:68
Span & operator-=(const Span &)
Definition: Time.cpp:108
Span & operator=(const Duration &)
Definition: Time.cpp:106
Span & operator+=(const Span &)
Definition: Time.cpp:107