JeVois  1.21
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Loading...
Searching...
No Matches
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// ####################################################################################################
29jevois::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// ####################################################################################################
47std::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// ####################################################################################################
140std::string const & jevois::Timer::stop()
141{ return stop(nullptr); }
142
143// ####################################################################################################
144// ####################################################################################################
145jevois::TimerOne::TimerOne(char const * prefix) :
146 itsPrefix(prefix)
147{ }
148
149// ####################################################################################################
151{
152 itsStartTime = std::chrono::steady_clock::now();
153}
154
155// ####################################################################################################
156std::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); }
void start()
Start a time measurement period.
Definition Timer.C:150
TimerOne(char const *prefix)
Constructor.
Definition Timer.C:145
std::string stop()
Same as the other signature of stop() except does not provide seconds, for python bindings.
Definition Timer.C:170
Timer(char const *prefix, size_t interval=100, int loglevel=LOG_INFO)
Constructor.
Definition Timer.C:29
std::string const & stop()
Same as the other signature of stop() except does not provide seconds, for python bindings.
Definition Timer.C:140
void start()
Start a time measurement period.
Definition Timer.C:40
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
Definition Log.H:230
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level.
Definition Log.H:173
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
Definition Log.H:211
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition Log.H:194
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:478