dynare/dynare++/kord/journal.cc

240 lines
6.6 KiB
C++
Raw Normal View History

/*
* Copyright © 2004-2011 Ondra Kamenik
2020-11-18 17:31:09 +01:00
* Copyright © 2019-2020 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include "journal.hh"
#include "kord_exception.hh"
#include <iomanip>
#include <cmath>
#include <ctime>
#include <limits>
#include <thread>
#ifndef _WIN32
# include <sys/time.h> // For getrusage()
# include <sys/resource.h> // For getrusage()
# include <sys/utsname.h> // For uname()
# include <cstdlib> // For getloadavg()
# include <unistd.h> // For sysconf()
# ifdef __APPLE__
# include <sys/types.h>
# include <sys/sysctl.h>
# endif
#else
# ifndef NOMINMAX
# define NOMINMAX // Do not define "min" and "max" macros
# endif
# include <windows.h> // For GlobalMemoryStatus()
#endif
const std::chrono::time_point<std::chrono::high_resolution_clock> SystemResources::start = std::chrono::high_resolution_clock::now();
#ifndef _WIN32
long
SystemResources::pageSize()
{
return sysconf(_SC_PAGESIZE);
}
#endif
long
SystemResources::availableMemory()
{
#if !defined(_WIN32) && !defined(__APPLE__)
return sysconf(_SC_AVPHYS_PAGES)*pageSize();
#elif defined(__APPLE__)
unsigned long usermem = 0;
size_t len = sizeof usermem;
static int mib[2] = { CTL_HW, HW_USERMEM };
int retval = sysctl(mib, 2, &usermem, &len, NULL, 0);
if (retval == 0)
return static_cast<long>(usermem);
return 0;
#else // _WIN32
MEMORYSTATUS memstat;
GlobalMemoryStatus(&memstat);
return memstat.dwAvailPhys;
#endif
}
SystemResources::SystemResources()
{
auto now = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> duration = now - start;
elapsed = duration.count();
#ifndef _WIN32
struct rusage rus;
getrusage(RUSAGE_SELF, &rus);
utime = rus.ru_utime.tv_sec+rus.ru_utime.tv_usec*1.0e-6;
stime = rus.ru_stime.tv_sec+rus.ru_stime.tv_usec*1.0e-6;
idrss = rus.ru_idrss;
majflt = rus.ru_majflt * pageSize();
#else
utime = std::numeric_limits<double>::quiet_NaN();
stime = std::numeric_limits<double>::quiet_NaN();
idrss = -1;
majflt = -1;
#endif
#ifndef _WIN32
getloadavg(&load_avg, 1);
#else
load_avg = std::numeric_limits<double>::quiet_NaN();
#endif
mem_avail = availableMemory();
}
void
SystemResources::diff(const SystemResources &pre)
{
utime -= pre.utime;
stime -= pre.stime;
elapsed -= pre.elapsed;
idrss -= pre.idrss;
majflt -= pre.majflt;
}
// JournalRecord::operator<<() symmetry code
JournalRecord &
JournalRecord::operator<<(const IntSequence &s)
{
operator<<('[');
for (int i = 0; i < s.size(); i++)
{
operator<<(s[i]);
if (i < s.size()-1)
operator<<(',');
}
operator<<(']');
return *this;
}
void
JournalRecord::writeFloatTabular(std::ostream &s, double d, int width)
{
// Number of digits of integer part
int intdigits = std::max(static_cast<int>(std::floor(log10(d))+1), 1);
int prec = std::max(width - 1 - intdigits, 0);
s << std::fixed << std::setw(width) << std::setprecision(prec) << d;
}
void
JournalRecord::writePrefix(const SystemResources &f)
{
constexpr double mb = 1024*1024;
std::ostringstream s;
s << std::setfill('0');
writeFloatTabular(s, f.elapsed, 7);
2019-12-20 14:36:20 +01:00
s << u8"" << recChar << std::setw(5) << ord << u8"";
writeFloatTabular(s, f.load_avg, 3);
2019-04-23 18:57:52 +02:00
s << u8"";
writeFloatTabular(s, f.mem_avail/mb, 5);
2019-04-23 18:57:52 +02:00
s << u8"│ │ ";
for (int i = 0; i < 2*journal.getDepth(); i++)
s << ' ';
prefix = s.str();
}
void
JournalRecordPair::writePrefixForEnd(const SystemResources &f)
{
constexpr double mb = 1024*1024;
SystemResources difnow;
difnow.diff(f);
std::ostringstream s;
s << std::setfill('0');
writeFloatTabular(s, f.elapsed+difnow.elapsed, 7);
2019-04-23 18:57:52 +02:00
s << u8"│E" << std::setw(5) << ord << u8"";
writeFloatTabular(s, difnow.load_avg, 3);
2019-04-23 18:57:52 +02:00
s << u8"";
writeFloatTabular(s, difnow.mem_avail/mb, 5);
2019-04-23 18:57:52 +02:00
s << u8"";
writeFloatTabular(s, difnow.majflt/mb, 6);
2019-04-23 18:57:52 +02:00
s << u8"";
for (int i = 0; i < 2*journal.getDepth(); i++)
s << ' ';
prefix_end = s.str();
}
JournalRecordPair::~JournalRecordPair()
{
journal.decrementDepth();
writePrefixForEnd(flash);
journal << prefix_end;
journal << mes;
journal << std::endl;
journal.flush();
}
JournalRecord &
endrec(JournalRecord &rec)
{
rec.journal << rec.prefix;
rec.journal << rec.mes;
rec.journal << std::endl;
rec.journal.flush();
rec.journal.incrementOrd();
return rec;
}
void
Journal::printHeader()
{
*this << "Dynare++ v. " << VERSION << '\n'
<< '\n'
<< u8"Copyright © 2004-2011 Ondra Kamenik\n"
2020-11-18 17:31:09 +01:00
<< u8"Copyright © 2019-2020 Dynare Team\n"
<< "Dynare++ comes with ABSOLUTELY NO WARRANTY and is distributed under the GNU GPL,\n"
<< "version 3 or later (see https://www.gnu.org/licenses/gpl.html)\n"
<< "\n\n"
<< "System info: ";
#ifndef _WIN32
utsname info;
uname(&info);
*this << info.sysname << " " << info.release << " " << info.version << " "
<< info.machine;
#else
*this << "Windows";
#endif
*this << ", processors online: " << std::thread::hardware_concurrency()
<< "\n\nStart time: ";
std::time_t t = std::time(nullptr);
// NB: in the date/time string, we avoid using locale-specific strings (#1751)
*this << std::put_time(std::localtime(&t),
#ifndef _WIN32
"%F %T %z"
#else
// Specifiers introduced in C++11 dont work under Windows…
"%Y-%m-%d %H:%M:%S"
#endif
)
<< "\n\n"
2019-04-23 18:57:52 +02:00
<< u8" ┌────╼ elapsed time (seconds) \n"
<< u8" │ ┌────╼ record unique identifier \n"
<< u8" │ │ ┌────╼ load average \n"
<< u8" │ │ │ ┌────╼ available memory (MB) \n"
<< u8" │ │ │ │ ┌─────╼ major faults (MB)\n"
<< u8" │ │ │ │ │ \n"
<< u8" ╽ ╽ ╽ ╽ ╽ \n";
}