TdZdd  1.1
A top-down/breadth-first decision diagram manipulation framework
ResourceUsage.hpp
1 /*
2  * TdZdd: a Top-down/Breadth-first Decision Diagram Manipulation Framework
3  * by Hiroaki Iwashita <iwashita@erato.ist.hokudai.ac.jp>
4  * Copyright (c) 2014 ERATO MINATO Project
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #pragma once
26 
27 #include <fstream>
28 #include <iomanip>
29 #include <iostream>
30 #include <sstream>
31 #ifndef _MSC_VER
32 #include <sys/time.h>
33 #endif
34 #ifndef _WIN32
35 #include <sys/resource.h>
36 #else
37 #define NOMINMAX
38 #include <windows.h>
39 #include <psapi.h>
40 #endif
41 
42 namespace tdzdd {
43 
44 #ifndef _MSC_VER
45 inline double getWallClockTime() {
46  struct timeval t;
47  gettimeofday(&t, 0);
48  return double(t.tv_sec) + double(t.tv_usec) / 1000000;
49 }
50 #else
51 inline double getWallClockTime() {
52  FILETIME t;
53  GetSystemTimeAsFileTime(&t);
54  return double(t.dwHighDateTime) / 10 + double(t.dwLowDateTime) / 10000000;
55 }
56 #endif
57 
58 struct ResourceUsage {
59  double etime;
60  double utime;
61  double stime;
62  long maxrss;
63 
64  ResourceUsage() {
65  update();
66  }
67 
68  ResourceUsage(double etime, double utime, double stime, long maxrss) :
69  etime(etime), utime(utime), stime(stime), maxrss(maxrss) {
70  }
71 
72  ResourceUsage& update() {
73  etime = getWallClockTime();
74 
75 #ifdef _WIN32
76  HANDLE h = GetCurrentProcess();
77  FILETIME ft_creat, ft_exit, ft_kernel, ft_user;
78  if (GetProcessTimes(h, &ft_creat, &ft_exit, &ft_kernel, &ft_user)) {
79  ULARGE_INTEGER ul_kernel, ul_user;
80  ul_kernel.LowPart = ft_kernel.dwLowDateTime;
81  ul_kernel.HighPart = ft_kernel.dwHighDateTime;
82  ul_user.LowPart = ft_user.dwLowDateTime;
83  ul_user.HighPart = ft_user.dwHighDateTime;
84  stime = ul_kernel.QuadPart * 1e-7;
85  utime = ul_user.QuadPart * 1e-7;
86  }
87 
88  PROCESS_MEMORY_COUNTERS pmc;
89  if (GetProcessMemoryInfo(h, &pmc, sizeof(pmc))) {
90  maxrss = pmc.WorkingSetSize / 1024;
91  }
92 #else
93  struct rusage s;
94  getrusage(RUSAGE_SELF, &s);
95  utime = s.ru_utime.tv_sec + s.ru_utime.tv_usec * 1e-6;
96  stime = s.ru_stime.tv_sec + s.ru_stime.tv_usec * 1e-6;
97  maxrss = s.ru_maxrss;
98 #ifdef __APPLE__
99  // Mac reports the maximum resident set size in bytes rather than in kilobytes.
100  maxrss /= 1024;
101 #endif
102 #endif
103  return *this;
104  }
105 
106  ResourceUsage operator+(ResourceUsage const& u) const {
107  return ResourceUsage(etime + u.etime, utime + u.utime, stime + u.stime,
108  std::max(maxrss, u.maxrss));
109  }
110 
111  ResourceUsage& operator+=(ResourceUsage const& u) {
112  etime += u.etime;
113  utime += u.utime;
114  stime += u.stime;
115  if (maxrss < u.maxrss) maxrss = u.maxrss;
116  return *this;
117  }
118 
119  ResourceUsage operator-(ResourceUsage const& u) const {
120  return ResourceUsage(etime - u.etime, utime - u.utime, stime - u.stime,
121  std::max(maxrss, u.maxrss));
122  }
123 
124  ResourceUsage& operator-=(ResourceUsage const& u) {
125  etime -= u.etime;
126  utime -= u.utime;
127  stime -= u.stime;
128  if (maxrss < u.maxrss) maxrss = u.maxrss;
129  return *this;
130  }
131 
132  std::string elapsedTime() const {
133  std::stringstream ss;
134  ss << std::fixed << std::setprecision(2) << etime << "s";
135  return ss.str();
136  }
137 
138  std::string userTime() const {
139  std::stringstream ss;
140  ss << std::fixed << std::setprecision(2) << utime << "s";
141  return ss.str();
142  }
143 
144  std::string memory() const {
145  std::stringstream ss;
146  ss << std::fixed << std::setprecision(0) << maxrss / 1024.0 << "MB";
147  return ss.str();
148  }
149 
150  friend std::ostream& operator<<(std::ostream& os, ResourceUsage const& u) {
151  std::ios_base::fmtflags backup = os.flags(std::ios::fixed);
152  os.setf(std::ios::fixed);
153 
154  os << std::setprecision(2) << u.etime << "s elapsed, ";
155  os << std::setprecision(2) << u.utime << "s user, ";
156  os << std::setprecision(0) << u.maxrss / 1024.0 << "MB";
157 
158  os.flags(backup);
159  return os;
160  }
161 };
162 
163 class ElapsedTimeCounter {
164  double totalTime;
165  double startTime;
166 
167 public:
168  ElapsedTimeCounter() :
169  totalTime(0), startTime(0) {
170  }
171 
172  ElapsedTimeCounter& reset() {
173  totalTime = 0;
174  return *this;
175  }
176 
177  ElapsedTimeCounter& start() {
178  startTime = getWallClockTime();
179  return *this;
180  }
181 
182  ElapsedTimeCounter& stop() {
183  totalTime += getWallClockTime() - startTime;
184  return *this;
185  }
186 
187  operator double() const {
188  return totalTime;
189  }
190 
191  friend std::ostream& operator<<(std::ostream& os,
192  ElapsedTimeCounter const& o) {
193  std::ios_base::fmtflags backup = os.flags(std::ios::fixed);
194  os.setf(std::ios::fixed);
195  os << std::setprecision(2) << o.totalTime << "s";
196  os.flags(backup);
197  return os;
198  }
199 };
200 
201 } // namespace tdzdd