JeVois  1.16
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Timer.C
Go to the documentation of this file.
1 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2016 by Laurent Itti, the University of Southern
4 // California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5 //
6 // This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7 // redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8 // Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10 // License for more details. You should have received a copy of the GNU General Public License along with this program;
11 // if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12 //
13 // Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14 // Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 /*! \file */
17 
18 #include <jevois/Debug/Timer.H>
19 #include <jevois/Debug/Log.H>
20 #include <jevois/Util/Utils.H>
21 #include <sstream>
22 #include <iomanip>
23 #include <fstream>
24 
25 #define _BSD_SOURCE /* See feature_test_macros(7) */
26 #include <stdlib.h> // for getloadavg()
27 
28 // ####################################################################################################
29 jevois::Timer::Timer(char const * prefix, size_t interval, int loglevel) :
30  itsPrefix(prefix), itsInterval(interval), itsLogLevel(loglevel), itsCount(0),
31  itsStartTime(std::chrono::steady_clock::now()), itsSecs(0.0),
32  itsMinSecs(1.0e30), itsMaxSecs(-1.0e30), itsStr("-- fps, --% CPU"),
33  itsStartTimeForCpu(std::chrono::steady_clock::now())
34 {
35  if (interval == 0) LFATAL("Interval must be > 0");
36  getrusage(RUSAGE_SELF, &itsStartRusage);
37 }
38 
39 // ####################################################################################################
41 {
42  itsStartTime = std::chrono::steady_clock::now();
43  if (itsCount == 0) { getrusage(RUSAGE_SELF, &itsStartRusage); itsStartTimeForCpu = itsStartTime; }
44 }
45 
46 // ####################################################################################################
47 std::string const & jevois::Timer::stop(double * seconds)
48 {
49  std::chrono::duration<double> const dur = std::chrono::steady_clock::now() - itsStartTime;
50  double secs = dur.count();
51  if (seconds) *seconds = secs;
52 
53  // Update average duration computation:
54  itsSecs += secs; ++itsCount;
55 
56  // Update min and max:
57  if (secs < itsMinSecs) itsMinSecs = secs;
58  if (secs > itsMaxSecs) itsMaxSecs = secs;
59 
60  if (itsCount >= itsInterval)
61  {
62  double avgsecs = itsSecs / itsInterval;
63  std::ostringstream ss;
64  ss << itsPrefix << " average (" << itsInterval << ") duration "; jevois::secs2str(ss, avgsecs);
65  ss << " ["; jevois::secs2str(ss, itsMinSecs); ss << " .. "; jevois::secs2str(ss, itsMaxSecs); ss<< ']';
66 
67  float fps = 0.0F;
68  if (avgsecs > 0.0) { fps = 1.0F / float(avgsecs); ss << " (" << fps << " fps)"; }
69 
70  switch (itsLogLevel)
71  {
72  case LOG_INFO: LINFO(ss.str()); break;
73  case LOG_ERR: LERROR(ss.str()); break;
74  case LOG_CRIT: LFATAL(ss.str()); break;
75  default: LDEBUG(ss.str());
76  }
77 
78  // Compute percent CPU used: since often we only run a chunk of code between start() and stop() that we want to
79  // evaluate, we cannot use itsSecs is as a denominator, we need the total elapsed time since the first call to
80  // start() over the current interval, hence our use of itsStartTimeForCpu here. Hence, note that the CPU load
81  // reported is for the whole process that is running, not just for the critical chunk of code that is executed
82  // between start() and stop(). Indeed the goal is to get an idea of the overall machine utilization:
83  rusage stoprusage; getrusage(RUSAGE_SELF, &stoprusage);
84 
85  double const user_secs = double(stoprusage.ru_utime.tv_sec) - double(itsStartRusage.ru_utime.tv_sec) +
86  (double(stoprusage.ru_utime.tv_usec) - double(itsStartRusage.ru_utime.tv_usec)) / 1000000.0;
87 
88  std::chrono::duration<double> const cpudur = std::chrono::steady_clock::now() - itsStartTimeForCpu;
89 
90  double const cpu = 100.0 * user_secs / cpudur.count();
91 
92 #ifdef JEVOIS_PLATFORM_PRO
93  // One JeVois Pro, use cpu 2 (big core) and thermal zone 1:
94  static char const tempname[] = "/sys/class/thermal/thermal_zone1/temp";
95  static char const freqname[] = "/sys/devices/system/cpu/cpu2/cpufreq/cpuinfo_cur_freq";
96  int freq = 2208;
97 #else
98  static char const tempname[] = "/sys/class/thermal/thermal_zone0/temp";
99  static char const freqname[] = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq";
100  int freq = 1344;
101 #endif
102 
103  // Get the CPU temperature:
104  int temp = 30;
105  std::ifstream ifs(tempname);
106  if (ifs.is_open())
107  {
108  try { std::string t; std::getline(ifs, t); temp = std::stoi(t); }
109  catch (...) { } // silently ignore any exception and keep default temp if any
110  ifs.close();
111  }
112 
113  // Most hosts report milli-degrees, JeVois-A33 platform reports straight degrees:
114 #ifndef JEVOIS_PLATFORM_A33
115  temp /= 1000;
116 #endif
117 
118  // Finally get the CPU frequency:
119  std::ifstream ifs2(freqname);
120  if (ifs2.is_open())
121  {
122  try { std::string f; std::getline(ifs2, f); freq = std::stoi(f) / 1000; }
123  catch (...) { } // silently ignore any exception and keep default freq if any
124  ifs2.close();
125  }
126 
127  // Ready to return all that info:
128  std::ostringstream os; os << std::fixed << std::setprecision(1) << fps << " fps, " << cpu << "% CPU, "
129  << temp << "C, " << freq << " MHz";
130  itsStr = os.str();
131 
132  // Get ready for the next cycle:
133  itsSecs = 0.0; itsMinSecs = 1.0e30; itsMaxSecs = -1.0e30; itsCount = 0;
134  }
135 
136  return itsStr;
137 }
138 
139 // ####################################################################################################
140 std::string const & jevois::Timer::stop()
141 { return stop(nullptr); }
142 
143 // ####################################################################################################
144 // ####################################################################################################
145 jevois::TimerOne::TimerOne(char const * prefix) :
146  itsPrefix(prefix)
147 { }
148 
149 // ####################################################################################################
151 {
152  itsStartTime = std::chrono::steady_clock::now();
153 }
154 
155 // ####################################################################################################
156 std::string jevois::TimerOne::stop(double * seconds)
157 {
158  std::chrono::duration<double> const dur = std::chrono::steady_clock::now() - itsStartTime;
159  double secs = dur.count();
160  if (seconds) *seconds = secs;
161 
162  std::ostringstream ss;
163  ss << itsPrefix << ": " << std::fixed << std::setprecision(1); jevois::secs2str(ss, secs);
164  if (secs == 0.0) ss << " (INF fps)"; else ss << " (" << 1.0 / secs << "fps)";
165 
166  return ss.str();
167 }
168 
169 // ####################################################################################################
171 { return stop(nullptr); }
jevois::Timer::Timer
Timer(char const *prefix, size_t interval=100, int loglevel=LOG_INFO)
Constructor.
Definition: Timer.C:29
LDEBUG
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level.
Definition: Log.H:160
jevois::Timer::start
void start()
Start a time measurement period.
Definition: Timer.C:40
LERROR
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
Definition: Log.H:198
jevois::TimerOne::start
void start()
Start a time measurement period.
Definition: Timer.C:150
jevois::Timer::stop
const std::string & stop()
Same as the other signature of stop() except does not provide seconds, for python bindings.
Definition: Timer.C:140
Log.H
Timer.H
LFATAL
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
Definition: Log.H:217
jevois::secs2str
std::string secs2str(double secs)
Report a duration given in seconds with variable units (ns, us, ms, or s), with precision of 2 decima...
Definition: Utils.C:435
Utils.H
jevois::TimerOne::stop
std::string stop()
Same as the other signature of stop() except does not provide seconds, for python bindings.
Definition: Timer.C:170
LINFO
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition: Log.H:181
jevois::TimerOne::TimerOne
TimerOne(char const *prefix)
Constructor.
Definition: Timer.C:145