8 #include <argos3/core/utility/logging/argos_log.h>
9 #include <argos3/core/utility/configuration/argos_configuration.h>
16 static double TV2Sec(const ::timeval& t_timeval) {
18 static_cast<double>(t_timeval.tv_sec) +
19 static_cast<double>(t_timeval.tv_usec) * 0.000001;
25 static double CPUUsage(const ::rusage& t_rusage,
26 double f_elapsed_time) {
28 (TV2Sec(t_rusage.ru_utime) +
29 TV2Sec(t_rusage.ru_stime)) /
36 #define DUMP_RUSAGE_FIELD_HUMAN_READABLE(MSG, FIELD) c_os << MSG ": " << t_resources.ru_ ## FIELD << std::endl;
38 const ::rusage& t_resources) {
39 double fUserTime = TV2Sec(t_resources.ru_utime);
40 c_os <<
"User time: " << fUserTime << std::endl;
41 double fSysTime = TV2Sec(t_resources.ru_stime);
42 c_os <<
"System time: " << fSysTime << std::endl;
62 #define DUMP_RUSAGE_FIELD_TABLE_ROW(FIELD) c_os << " " << t_resources.ru_ ## FIELD;
64 const ::rusage& t_resources) {
65 double fUserTime = TV2Sec(t_resources.ru_utime);
67 double fSysTime = TV2Sec(t_resources.ru_stime);
68 c_os <<
" " << fSysTime;
88 #define DIFF_RUSAGE_FIELD(FIELD) tResult.ru_ ## FIELD = t_resource1.ru_ ## FIELD - t_resource2.ru_ ## FIELD;
90 const ::rusage& t_resource2) {
119 m_cOutFile.open(str_file_name.c_str(),
120 std::ios::trunc | std::ios::out);
123 m_cOutFile.open(str_file_name.c_str(),
124 std::ios::app | std::ios::out);
126 LOG <<
"[INFO] Opened file \"" << str_file_name <<
"\" for profiling." << std::endl;
127 int nError = pthread_mutex_init(&m_tThreadResourceUsageMutex,
nullptr);
138 pthread_mutex_destroy(&m_tThreadResourceUsageMutex);
161 if(b_human_readable) {
162 FlushHumanReadable();
173 pthread_mutex_lock(&m_tThreadResourceUsageMutex);
174 ::rusage tResourceUsage;
178 getrusage(RUSAGE_SELF, &tResourceUsage);
180 ::getrusage(::RUSAGE_THREAD, &tResourceUsage);
182 m_vecThreadResourceUsage.push_back(tResourceUsage);
183 pthread_mutex_unlock(&m_tThreadResourceUsageMutex);
189 void CProfiler::FlushHumanReadable() {
190 m_cOutFile <<
"[profiled portion overall]" << std::endl << std::endl;
191 double fStartTime = TV2Sec(m_tWallClockStart);
192 double fEndTime = TV2Sec(m_tWallClockEnd);
193 double fElapsedTime = fEndTime - fStartTime;
194 m_cOutFile <<
"Wall clock time: " << fElapsedTime << std::endl;
195 ::rusage tDiffResourceUsage = m_tResourceUsageEnd - m_tResourceUsageStart;
196 m_cOutFile <<
"CPU usage: " << CPUUsage(tDiffResourceUsage, fElapsedTime) <<
"%" << std::endl;
198 m_cOutFile << std::endl <<
"[profiled portion start]" << std::endl << std::endl;
200 m_cOutFile << std::endl <<
"[profiled portion end]" << std::endl << std::endl;
202 m_cOutFile << std::endl <<
"[process overall]" << std::endl << std::endl;
203 ::rusage tResourceUsage;
205 getrusage(RUSAGE_SELF, &tResourceUsage);
207 ::getrusage(::RUSAGE_SELF, &tResourceUsage);
210 if(! m_vecThreadResourceUsage.empty()) {
211 for(
size_t i = 0; i < m_vecThreadResourceUsage.size(); ++i) {
212 m_cOutFile << std::endl <<
"[thread #" << i <<
" overall]" << std::endl << std::endl;
213 m_cOutFile <<
"CPU usage: " << CPUUsage(m_vecThreadResourceUsage[i], fElapsedTime) <<
"%" << std::endl;
222 void CProfiler::FlushAsTable() {
223 double fStartTime = TV2Sec(m_tWallClockStart);
224 double fEndTime = TV2Sec(m_tWallClockEnd);
225 double fElapsedTime = fEndTime - fStartTime;
226 ::rusage tDiffResourceUsage = m_tResourceUsageEnd - m_tResourceUsageStart;
227 m_cOutFile <<
"ProfPortion " << fElapsedTime <<
" "
228 << CPUUsage(tDiffResourceUsage, fElapsedTime) <<
" ";
230 m_cOutFile << std::endl <<
"PortionStart 0 0 ";
232 m_cOutFile << std::endl <<
"PortionEnd 0 0 ";
234 m_cOutFile << std::endl <<
"Overall 0 0 ";
235 ::rusage tResourceUsage;
237 getrusage(RUSAGE_SELF, &tResourceUsage);
239 ::getrusage(::RUSAGE_SELF, &tResourceUsage);
242 if(! m_vecThreadResourceUsage.empty()) {
243 for(
size_t i = 0; i < m_vecThreadResourceUsage.size(); ++i) {
244 m_cOutFile << std::endl <<
"thread_" << i <<
" 0 "
245 << CPUUsage(m_vecThreadResourceUsage[i], fElapsedTime) <<
" ";
249 m_cOutFile << std::endl;
255 void CProfiler::StartWallClock() {
256 ::gettimeofday(&m_tWallClockStart,
nullptr);
262 void CProfiler::StopWallClock() {
263 ::gettimeofday(&m_tWallClockEnd,
nullptr);
269 void CProfiler::StartCPUProfiler() {
271 getrusage(RUSAGE_SELF, &m_tResourceUsageStart);
273 ::getrusage(::RUSAGE_SELF, &m_tResourceUsageStart);
280 void CProfiler::StopCPUProfiler() {
282 getrusage(RUSAGE_SELF, &m_tResourceUsageEnd);
284 ::getrusage(::RUSAGE_SELF, &m_tResourceUsageEnd);
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
#define DUMP_RUSAGE_FIELD_TABLE_ROW(FIELD)
#define DUMP_RUSAGE_FIELD_HUMAN_READABLE(MSG, FIELD)
#define DIFF_RUSAGE_FIELD(FIELD)
The namespace containing all the ARGoS related code.
void DumpResourceUsageAsTableRow(std::ostream &c_os, const ::rusage &t_resources)
CARGoSLog LOG(std::cout, SLogColor(ARGOS_LOG_ATTRIBUTE_BRIGHT, ARGOS_LOG_COLOR_GREEN))
::rusage operator-(const ::rusage &t_resource1, const ::rusage &t_resource2)
void DumpResourceUsageHumanReadable(std::ostream &c_os, const ::rusage &t_resources)
void CollectThreadResourceUsage()
void Flush(bool b_human_readable)
CProfiler(const std::string &str_file_name, bool b_trunc=true)