spot: Add %R, %[..]R common option.

For #189.

* NEWS: Update.
* bin/autfilt.cc: Replace stopwatch with process_timer.
* bin/dstar2tgba.cc: Replace stopwatch with process_timer.
* bin/ltl2tgba.cc: Replace stopwatch with process_timer.
* bin/ltlcross.cc: Replace stopwatch with process_timer.
* bin/ltldo.cc: Replace stopwatch with process_timer.
* bin/randaut.cc: Replace stopwatch with process_timer.
* bin/common_aoutput.hh: Implement process_timer, integrate it.
* bin/common_aoutput.cc: Integrate process_timer and implement new
print method.
* spot/misc/timer.hh: Modify timer class and timeinfo struct
i.e. add cutime (children_utime) and cstime (children_stime).
* spot/misc/timer.cc: Help code to behave as before all this.
* spot/twaalgos/dtbasat.cc: Help print_log to behave as before
all this.
* spot/twaalgos/dtwasat.cc: Help print_log to behave as before
all this.
* spot/misc/formater.hh: Add operator<< for spot::timer.
This commit is contained in:
Alexandre GBAGUIDI AISSE 2016-10-24 17:46:26 +02:00 committed by Alexandre Duret-Lutz
parent 3eafbc823c
commit 6ed380709d
14 changed files with 277 additions and 79 deletions

6
NEWS
View file

@ -6,6 +6,12 @@ New in spot 2.1.2.dev (not yet released)
LTL over finite words) model checking to LTL model checking. This LTL over finite words) model checking to LTL model checking. This
is based on a transformation by De Giacomo & Vardi (IJCAI'13). is based on a transformation by De Giacomo & Vardi (IJCAI'13).
* autfilt, dstar2tgba, ltl2tgba, ltlcross, ltldo learned to time any
task in a more precise way thanks to %R, %[LETTER]R option. User time,
system time or children processing time or ... (see --help) can be
measured separately. A typical use-case is to exclude time spent
inside ltldo by keeping only time spent in each executed tool.
Library: Library:
* from_ltlf() is a new function implementing the --from-ltlf * from_ltlf() is a new function implementing the --from-ltlf

View file

@ -963,8 +963,8 @@ namespace
process_automaton(const spot::const_parsed_aut_ptr& haut, process_automaton(const spot::const_parsed_aut_ptr& haut,
const char* filename) const char* filename)
{ {
spot::stopwatch sw; process_timer timer;
sw.start(); timer.start();
// If --stats or --name is used, duplicate the automaton so we // If --stats or --name is used, duplicate the automaton so we
// never modify the original automaton (e.g. with // never modify the original automaton (e.g. with
@ -1183,8 +1183,7 @@ namespace
run->project(aut)->highlight(word_aut.second); run->project(aut)->highlight(word_aut.second);
} }
const double conversion_time = sw.stop(); timer.stop();
if (opt->uniq) if (opt->uniq)
{ {
auto tmp = auto tmp =
@ -1197,8 +1196,7 @@ namespace
++match_count; ++match_count;
printer.print(aut, nullptr, filename, -1, conversion_time, haut, printer.print(aut, timer, nullptr, filename, -1, haut, prefix, suffix);
prefix, suffix);
if (opt_max_count >= 0 && match_count >= opt_max_count) if (opt_max_count >= 0 && match_count >= opt_max_count)
abort_run = true; abort_run = true;

View file

@ -20,20 +20,19 @@
#include "common_sys.hh" #include "common_sys.hh"
#include "error.h" #include "error.h"
#include "argmatch.h" #include "argmatch.h"
#include "common_aoutput.hh" #include "common_aoutput.hh"
#include "common_post.hh" #include "common_post.hh"
#include "common_cout.hh" #include "common_cout.hh"
#include <unistd.h>
#include <spot/twa/bddprint.hh> #include <spot/twa/bddprint.hh>
#include <spot/twaalgos/dot.hh> #include <spot/twaalgos/dot.hh>
#include <spot/twaalgos/lbtt.hh>
#include <spot/twaalgos/hoa.hh> #include <spot/twaalgos/hoa.hh>
#include <spot/twaalgos/neverclaim.hh>
#include <spot/twaalgos/stutter.hh>
#include <spot/twaalgos/isunamb.hh> #include <spot/twaalgos/isunamb.hh>
#include <spot/twaalgos/lbtt.hh>
#include <spot/twaalgos/neverclaim.hh>
#include <spot/twaalgos/strength.hh> #include <spot/twaalgos/strength.hh>
#include <spot/twaalgos/stutter.hh>
automaton_format_t automaton_format = Hoa; automaton_format_t automaton_format = Hoa;
static const char* automaton_format_opt = nullptr; static const char* automaton_format_opt = nullptr;
@ -173,6 +172,11 @@ static const argp_option io_options[] =
"using the following LETTERS, possibly concatenated: (a) accepting, " "using the following LETTERS, possibly concatenated: (a) accepting, "
"(r) rejecting, (v) trivial, (t) terminal, (w) weak, " "(r) rejecting, (v) trivial, (t) terminal, (w) weak, "
"(iw) inherently weak. Use uppercase letters to negate them.", 0 }, "(iw) inherently weak. Use uppercase letters to negate them.", 0 },
{ "%R, %[LETTERS]R", 0, nullptr,
OPTION_DOC | OPTION_NO_USAGE,
"CPU time (excluding parsing), in seconds; Add LETTERS to restrict to"
"(u) user time, (s) system time or to omit (p) parent processes, "
"(c) children processes.", 0 },
{ "%N, %n", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%N, %n", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of nondeterministic states", 0 }, "number of nondeterministic states", 0 },
{ "%D, %d", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%D, %d", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
@ -180,7 +184,7 @@ static const argp_option io_options[] =
{ "%P, %p", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%P, %p", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"1 if the automaton is complete, 0 otherwise", 0 }, "1 if the automaton is complete, 0 otherwise", 0 },
{ "%r", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%r", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"processing time (excluding parsing) in seconds", 0 }, "wall-clock time elapsed in seconds (excluding parsing)", 0 },
{ "%W, %w", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%W, %w", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"one word accepted by the automaton", 0 }, "one word accepted by the automaton", 0 },
{ "%%", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%%", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
@ -225,6 +229,11 @@ static const argp_option o_options[] =
"using the following LETTERS, possibly concatenated: (a) accepting, " "using the following LETTERS, possibly concatenated: (a) accepting, "
"(r) rejecting, (v) trivial, (t) terminal, (w) weak, " "(r) rejecting, (v) trivial, (t) terminal, (w) weak, "
"(iw) inherently weak. Use uppercase letters to negate them.", 0 }, "(iw) inherently weak. Use uppercase letters to negate them.", 0 },
{ "%R, %[LETTERS]R", 0, nullptr,
OPTION_DOC | OPTION_NO_USAGE,
"CPU time (excluding parsing), in seconds; Add LETTERS to restrict to"
"(u) user time, (s) system time or to omit (p) parent processes, "
"(c) children processes.", 0 },
{ "%n", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%n", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of nondeterministic states in output", 0 }, "number of nondeterministic states in output", 0 },
{ "%d", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%d", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
@ -232,7 +241,7 @@ static const argp_option o_options[] =
{ "%p", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%p", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"1 if the output is complete, 0 otherwise", 0 }, "1 if the output is complete, 0 otherwise", 0 },
{ "%r", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%r", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"processing time (excluding parsing) in seconds", 0 }, "wall-clock time elapsed in seconds (excluding parsing)", 0 },
{ "%w", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%w", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"one word accepted by the output automaton", 0 }, "one word accepted by the output automaton", 0 },
{ "%%", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%%", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
@ -351,6 +360,7 @@ hoa_stat_printer::hoa_stat_printer(std::ostream& os, const char* format,
declare('>', &csv_suffix_); declare('>', &csv_suffix_);
declare('F', &filename_); declare('F', &filename_);
declare('L', &location_); declare('L', &location_);
declare('R', &timer_);
if (input != ltl_input) if (input != ltl_input)
declare('f', &filename_); // Override the formula printer. declare('f', &filename_); // Override the formula printer.
declare('h', &output_aut_); declare('h', &output_aut_);
@ -362,9 +372,12 @@ std::ostream&
hoa_stat_printer::print(const spot::const_parsed_aut_ptr& haut, hoa_stat_printer::print(const spot::const_parsed_aut_ptr& haut,
const spot::const_twa_graph_ptr& aut, const spot::const_twa_graph_ptr& aut,
spot::formula f, spot::formula f,
const char* filename, int loc, double run_time, const char* filename, int loc, process_timer& ptimer,
const char* csv_prefix, const char* csv_suffix) const char* csv_prefix, const char* csv_suffix)
{ {
timer_ = ptimer.dt;
double run_time = ptimer.get_lap_sw();
filename_ = filename ? filename : ""; filename_ = filename ? filename : "";
csv_prefix_ = csv_prefix ? csv_prefix : ""; csv_prefix_ = csv_prefix ? csv_prefix : "";
csv_suffix_ = csv_suffix ? csv_suffix : ""; csv_suffix_ = csv_suffix ? csv_suffix : "";
@ -494,12 +507,13 @@ automaton_printer::automaton_printer(stat_style input)
void void
automaton_printer::print(const spot::twa_graph_ptr& aut, automaton_printer::print(const spot::twa_graph_ptr& aut,
// Time for statistics
process_timer& ptimer,
spot::formula f, spot::formula f,
// Input location for errors and statistics. // Input location for errors and statistics.
const char* filename, const char* filename,
int loc, int loc,
// Time and input automaton for statistics // input automaton for statistics
double time,
const spot::const_parsed_aut_ptr& haut, const spot::const_parsed_aut_ptr& haut,
const char* csv_prefix, const char* csv_prefix,
const char* csv_suffix) const char* csv_suffix)
@ -518,7 +532,7 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
if (opt_name) if (opt_name)
{ {
name.str(""); name.str("");
namer.print(haut, aut, f, filename, loc, time, csv_prefix, csv_suffix); namer.print(haut, aut, f, filename, loc, ptimer, csv_prefix, csv_suffix);
aut->set_named_prop("automaton-name", new std::string(name.str())); aut->set_named_prop("automaton-name", new std::string(name.str()));
} }
@ -526,7 +540,7 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
if (opt_output) if (opt_output)
{ {
outputname.str(""); outputname.str("");
outputnamer.print(haut, aut, f, filename, loc, time, outputnamer.print(haut, aut, f, filename, loc, ptimer,
csv_prefix, csv_suffix); csv_prefix, csv_suffix);
std::string fname = outputname.str(); std::string fname = outputname.str();
auto p = outputfiles.emplace(fname, nullptr); auto p = outputfiles.emplace(fname, nullptr);
@ -556,7 +570,7 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
break; break;
case Stats: case Stats:
statistics.set_output(*out); statistics.set_output(*out);
statistics.print(haut, aut, f, filename, loc, time, statistics.print(haut, aut, f, filename, loc, ptimer,
csv_prefix, csv_suffix) << '\n'; csv_prefix, csv_suffix) << '\n';
break; break;
} }
@ -590,3 +604,70 @@ void printable_automaton::print(std::ostream& os, const char* pos) const
} }
print_hoa(os, val_, options.c_str()); print_hoa(os, val_, options.c_str());
} }
void printable_timer::print(std::ostream& os, const char* pos) const
{
double res = 0;
if (*pos != '[')
{
res = val_.get_uscp(true, true, true, true);
os << res / sysconf(_SC_CLK_TCK);
return;
}
bool user = false;
bool system = false;
bool parent = false;
bool children = false;
const char* beg = pos;
auto error = [&](std::string str)
{
std::ostringstream tmp;
const char* end = std::strchr(pos, ']');
tmp << "unknown option '" << str << "' in '%" << std::string(beg, end + 2)
<< '\'';
throw std::runtime_error(tmp.str());
};
do
{
++pos;
switch (*pos)
{
case 'u':
user = true;
break;
case 's':
system = true;
break;
case 'p':
parent = true;
break;
case 'c':
children = true;
break;
case ' ':
case '\t':
case '\n':
case ',':
case ']':
break;
default:
error(std::string(pos, pos + 1));
}
} while (*pos != ']');
if (user && !parent && !children)
parent = children = true;
if (system && !parent && !children)
parent = children = true;
if (parent && !user && !system)
user = system = true;
if (children && !user && !system)
user = system = true;
res = val_.get_uscp(user, system, children, parent);
os << res / sysconf(_SC_CLK_TCK);
}

View file

@ -20,18 +20,17 @@
#pragma once #pragma once
#include "common_sys.hh" #include "common_sys.hh"
#include "common_file.hh"
#include <argp.h> #include <argp.h>
#include <memory> #include <memory>
#include <spot/misc/timer.hh>
#include <spot/parseaut/public.hh> #include <spot/parseaut/public.hh>
#include <spot/twaalgos/stats.hh>
#include <spot/twaalgos/sccinfo.hh>
#include <spot/twaalgos/gtec/gtec.hh> #include <spot/twaalgos/gtec/gtec.hh>
#include <spot/twaalgos/word.hh>
#include <spot/twaalgos/isdet.hh> #include <spot/twaalgos/isdet.hh>
#include "common_file.hh" #include <spot/twaalgos/sccinfo.hh>
#include <spot/twaalgos/stats.hh>
#include <spot/twaalgos/word.hh>
// Format for automaton output // Format for automaton output
@ -74,6 +73,40 @@ struct printable_automaton final:
void print(std::ostream& os, const char* pos) const override; void print(std::ostream& os, const char* pos) const override;
}; };
struct process_timer
{
void start()
{
sw.start();
dt.start();
}
void stop()
{
// sw.stop() --> It always returns the duration since the last call to
// start(). Therefore, it wont't stop timing, moreover, it can be called
// multiple times.
sw_lap_ = sw.stop();
dt.stop();
}
double get_lap_sw()
{
return sw_lap_;
}
spot::timer dt;
spot::stopwatch sw;
double sw_lap_ = 0;
};
struct printable_timer final:
public spot::printable_value<spot::timer>
{
using spot::printable_value<spot::timer>::operator=;
void print(std::ostream& os, const char* pos) const override;
};
/// \brief prints various statistics about a TGBA /// \brief prints various statistics about a TGBA
/// ///
/// This object can be configured to display various statistics /// This object can be configured to display various statistics
@ -96,7 +129,7 @@ public:
print(const spot::const_parsed_aut_ptr& haut, print(const spot::const_parsed_aut_ptr& haut,
const spot::const_twa_graph_ptr& aut, const spot::const_twa_graph_ptr& aut,
spot::formula f, spot::formula f,
const char* filename, int loc, double run_time, const char* filename, int loc, process_timer& ptimer,
const char* csv_prefix, const char* csv_suffix); const char* csv_prefix, const char* csv_suffix);
private: private:
@ -117,6 +150,7 @@ private:
spot::printable_value<unsigned> haut_complete_; spot::printable_value<unsigned> haut_complete_;
spot::printable_value<const char*> csv_prefix_; spot::printable_value<const char*> csv_prefix_;
spot::printable_value<const char*> csv_suffix_; spot::printable_value<const char*> csv_suffix_;
printable_timer timer_;
printable_automaton input_aut_; printable_automaton input_aut_;
printable_automaton output_aut_; printable_automaton output_aut_;
}; };
@ -132,18 +166,17 @@ class automaton_printer
std::map<std::string, std::unique_ptr<output_file>> outputfiles; std::map<std::string, std::unique_ptr<output_file>> outputfiles;
public: public:
automaton_printer(stat_style input = no_input); automaton_printer(stat_style input = no_input);
~automaton_printer(); ~automaton_printer();
void void
print(const spot::twa_graph_ptr& aut, print(const spot::twa_graph_ptr& aut,
process_timer& ptimer,
spot::formula f = nullptr, spot::formula f = nullptr,
// Input location for errors and statistics. // Input location for errors and statistics.
const char* filename = nullptr, const char* filename = nullptr,
int loc = -1, int loc = -1,
// Time and input automaton for statistics // Time and input automaton for statistics
double time = 0.0,
const spot::const_parsed_aut_ptr& haut = nullptr, const spot::const_parsed_aut_ptr& haut = nullptr,
const char* csv_prefix = nullptr, const char* csv_prefix = nullptr,
const char* csv_suffix = nullptr); const char* csv_suffix = nullptr);

View file

@ -213,13 +213,12 @@ namespace
process_automaton(const spot::const_parsed_aut_ptr& haut, process_automaton(const spot::const_parsed_aut_ptr& haut,
const char* filename) const char* filename)
{ {
spot::stopwatch sw; process_timer timer;
sw.start(); timer.start();
auto nba = spot::to_generalized_buchi(haut->aut); auto nba = spot::to_generalized_buchi(haut->aut);
auto aut = post.run(nba, nullptr); auto aut = post.run(nba, nullptr);
const double conversion_time = sw.stop(); timer.stop();
printer.print(aut, timer, nullptr, filename, -1, haut);
printer.print(aut, nullptr, filename, -1, conversion_time, haut);
flush_cout(); flush_cout();
return 0; return 0;
} }

View file

@ -139,12 +139,12 @@ namespace
s.c_str()); s.c_str());
} }
spot::stopwatch sw; process_timer timer;
sw.start(); timer.start();
auto aut = trans.run(&f); auto aut = trans.run(&f);
const double translation_time = sw.stop(); timer.stop();
printer.print(aut, f, filename, linenum, translation_time, nullptr, printer.print(aut, timer, f, filename, linenum, nullptr,
prefix, suffix); prefix, suffix);
return 0; return 0;
} }

View file

@ -39,6 +39,7 @@
#include "common_file.hh" #include "common_file.hh"
#include "common_finput.hh" #include "common_finput.hh"
#include "common_hoaread.hh" #include "common_hoaread.hh"
#include "common_aoutput.hh"
#include <spot/parseaut/public.hh> #include <spot/parseaut/public.hh>
#include <spot/tl/print.hh> #include <spot/tl/print.hh>
#include <spot/tl/apcollect.hh> #include <spot/tl/apcollect.hh>
@ -534,11 +535,10 @@ namespace
std::string cmd = command.str(); std::string cmd = command.str();
std::cerr << "Running [" << l << translator_num << "]: " std::cerr << "Running [" << l << translator_num << "]: "
<< cmd << std::endl; << cmd << std::endl;
spot::stopwatch sw; process_timer timer;
sw.start(); timer.start();
int es = exec_with_timeout(cmd.c_str()); int es = exec_with_timeout(cmd.c_str());
double duration = sw.stop(); timer.stop();
const char* status_str = nullptr; const char* status_str = nullptr;
spot::twa_graph_ptr res = nullptr; spot::twa_graph_ptr res = nullptr;
@ -619,7 +619,7 @@ namespace
statistics* st = &(*fstats)[translator_num]; statistics* st = &(*fstats)[translator_num];
st->status_str = status_str; st->status_str = status_str;
st->status_code = es; st->status_code = es;
st->time = duration; st->time = timer.get_lap_sw();
// Compute statistics. // Compute statistics.
if (res) if (res)

View file

@ -168,7 +168,7 @@ namespace
} }
spot::twa_graph_ptr spot::twa_graph_ptr
translate(unsigned int translator_num, bool& problem, double& duration) translate(unsigned int translator_num, bool& problem, process_timer& timer)
{ {
output.reset(translator_num); output.reset(translator_num);
@ -178,10 +178,9 @@ namespace
std::string cmd = command.str(); std::string cmd = command.str();
//std::cerr << "Running [" << l << translator_num << "]: " //std::cerr << "Running [" << l << translator_num << "]: "
// << cmd << std::endl; // << cmd << std::endl;
spot::stopwatch sw; timer.start();
sw.start();
int es = exec_with_timeout(cmd.c_str()); int es = exec_with_timeout(cmd.c_str());
duration = sw.stop(); timer.stop();
spot::twa_graph_ptr res = nullptr; spot::twa_graph_ptr res = nullptr;
problem = false; problem = false;
@ -316,8 +315,8 @@ namespace
for (unsigned t = 0; t < ts; ++t) for (unsigned t = 0; t < ts; ++t)
{ {
bool problem; bool problem;
double translation_time; process_timer timer;
auto aut = runner.translate(t, problem, translation_time); auto aut = runner.translate(t, problem, timer);
if (problem) if (problem)
{ {
if (errors_opt == errors_abort) if (errors_opt == errors_abort)
@ -333,7 +332,7 @@ namespace
aut = post.run(aut, f); aut = post.run(aut, f);
cmdname = translators[t].name; cmdname = translators[t].name;
roundval = round; roundval = round;
printer.print(aut, f, filename, linenum, translation_time, printer.print(aut, timer, f, filename, linenum,
nullptr, prefix, suffix); nullptr, prefix, suffix);
}; };
} }

View file

@ -341,8 +341,8 @@ main(int argc, char** argv)
for (;;) for (;;)
{ {
spot::stopwatch sw; process_timer timer;
sw.start(); timer.start();
if (ap_count_given.max > 0 if (ap_count_given.max > 0
&& ap_count_given.min != ap_count_given.max) && ap_count_given.min != ap_count_given.max)
@ -395,10 +395,10 @@ main(int argc, char** argv)
trials = max_trials; trials = max_trials;
} }
auto runtime = sw.stop(); timer.stop();
printer.print(aut, nullptr, printer.print(aut, timer, nullptr,
opt_seed_str, automaton_num, runtime, nullptr); opt_seed_str, automaton_num, nullptr);
++automaton_num; ++automaton_num;
if (opt_automata > 0 && automaton_num >= opt_automata) if (opt_automata > 0 && automaton_num >= opt_automata)

View file

@ -20,10 +20,13 @@
#pragma once #pragma once
#include <spot/misc/common.hh> #include <spot/misc/common.hh>
#include <spot/misc/timer.hh>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
#define UNUSED(expr) do { (void)(expr); } while (0)
namespace spot namespace spot
{ {
class printable class printable
@ -85,6 +88,15 @@ namespace spot
} }
}; };
// This function was defined to avoid compilation error when
// instantiating function spot::printable_value<spot::timer>::print
// because of: os << val_;
std::ostream& operator<<(std::ostream& os, const timer& dt)
{
UNUSED(dt);
return os;
}
/// The default callback simply writes "%c". /// The default callback simply writes "%c".
class printable_id: public printable class printable_id: public printable
{ {

View file

@ -27,6 +27,15 @@
namespace spot namespace spot
{ {
/*
std::ostream& operator<<(std::ostream& os, const timer& dt)
{
os << "utime<" << dt.utime() << ">, cutime<" << dt.cutime()
<< ">, stime<" << dt.stime() << ">, cstime<" << dt.cstime() << '>';
return os;
}
*/
std::ostream& std::ostream&
timer_map::print(std::ostream& os) const timer_map::print(std::ostream& os) const
@ -39,8 +48,11 @@ namespace spot
{ {
total.utime += i->second.first.utime(); total.utime += i->second.first.utime();
total.stime += i->second.first.stime(); total.stime += i->second.first.stime();
total.cutime += i->second.first.cutime();
total.cstime += i->second.first.cstime();
} }
clock_t grand_total = total.utime + total.stime; clock_t grand_total = total.utime + total.cutime
+ total.stime + total.cstime;
os << std::setw(23) << "" os << std::setw(23) << ""
<< "| user time | sys. time | total |" << "| user time | sys. time | total |"
@ -61,18 +73,21 @@ namespace spot
const char* sep = t.is_running() ? "+|" : " |"; const char* sep = t.is_running() ? "+|" : " |";
os << std::setw(22) << name << sep os << std::setw(22) << name << sep
<< std::setw(6) << t.utime() << ' ' << std::setw(6) << t.utime() + t.cutime() << ' '
<< std::setw(8) << (total.utime ? << std::setw(8) << (total.utime ?
100.0 * t.utime() / total.utime : 0.) 100.0 * (t.utime() + t.cutime())
/ (total.utime + total.cutime) : 0.)
<< sep << sep
<< std::setw(6) << t.stime() << ' ' << std::setw(6) << t.stime() + t.cstime() << ' '
<< std::setw(8) << (total.stime ? << std::setw(8) << (total.stime ?
100.0 * t.stime() / total.stime : 0.) 100.0 * (t.stime() +t.cstime())
/ (total.stime + total.cstime) : 0.)
<< sep << sep
<< std::setw(6) << t.utime() + t.stime() << ' ' << std::setw(6) << t.utime() + t.cutime() + t.stime()
+ t.cstime() << ' '
<< std::setw(8) << (grand_total ? << std::setw(8) << (grand_total ?
(100.0 * (t.utime() + t.stime()) / (100.0 * (t.utime() + t.cutime() + t.stime()
grand_total) : 0.) + t.cstime()) / grand_total) : 0.)
<< sep << sep
<< std::setw(4) << i->second.second << std::setw(4) << i->second.second
<< std::endl; << std::endl;
@ -80,10 +95,10 @@ namespace spot
os << std::setw(79) << std::setfill('-') << "" << std::setfill(' ') os << std::setw(79) << std::setfill('-') << "" << std::setfill(' ')
<< std::endl << std::endl
<< std::setw(22) << "TOTAL" << " |" << std::setw(22) << "TOTAL" << " |"
<< std::setw(6) << total.utime << ' ' << std::setw(6) << total.utime + total.cutime << ' '
<< std::setw(8) << 100. << std::setw(8) << 100.
<< " |" << " |"
<< std::setw(6) << total.stime << ' ' << std::setw(6) << total.stime + total.cstime << ' '
<< std::setw(8) << 100. << std::setw(8) << 100.
<< " |" << " |"
<< std::setw(6) << grand_total << ' ' << std::setw(6) << grand_total << ' '

View file

@ -66,19 +66,22 @@ namespace spot
} }
}; };
/// A structure to record elapsed time in clock ticks. /// A structure to record elapsed time in clock ticks.
struct time_info struct time_info
{ {
time_info() time_info()
: utime(0), stime(0) : utime(0), stime(0), cutime(0), cstime(0)
{ {
} }
clock_t utime; clock_t utime;
clock_t stime; clock_t stime;
clock_t cutime;
clock_t cstime;
}; };
/// A timekeeper that accumulate interval of time. /// A timekeeper that accumulate interval of time in a more detailed way.
/// For instance, you can get the time spent with or without children
/// processes.
class timer class timer
{ {
public: public:
@ -96,8 +99,10 @@ namespace spot
#ifdef SPOT_HAVE_TIMES #ifdef SPOT_HAVE_TIMES
struct tms tmp; struct tms tmp;
times(&tmp); times(&tmp);
start_.utime = tmp.tms_utime + tmp.tms_cutime; start_.utime = tmp.tms_utime;
start_.stime = tmp.tms_stime + tmp.tms_cstime; start_.cutime = tmp.tms_cutime;
start_.stime = tmp.tms_stime;
start_.cstime = tmp.tms_cstime;
#else #else
start_.utime = clock(); start_.utime = clock();
#endif #endif
@ -110,8 +115,10 @@ namespace spot
#ifdef SPOT_HAVE_TIMES #ifdef SPOT_HAVE_TIMES
struct tms tmp; struct tms tmp;
times(&tmp); times(&tmp);
total_.utime += tmp.tms_utime + tmp.tms_cutime - start_.utime; total_.utime += tmp.tms_utime - start_.utime;
total_.stime += tmp.tms_stime + tmp.tms_cstime - start_.stime; total_.cutime += tmp.tms_cutime - start_.cutime;
total_.stime += tmp.tms_stime - start_.stime;
total_.cstime += tmp.tms_cstime - start_.cstime;
#else #else
total_.utime += clock() - start_.utime; total_.utime += clock() - start_.utime;
#endif #endif
@ -119,7 +126,8 @@ namespace spot
running = false; running = false;
} }
/// \brief Return the user time of all accumulated interval. /// \brief Return the user time of the current process (without children)
/// of all accumulated interval.
/// ///
/// Any time interval that has been start()ed but not stop()ed /// Any time interval that has been start()ed but not stop()ed
/// will not be accounted for. /// will not be accounted for.
@ -129,7 +137,18 @@ namespace spot
return total_.utime; return total_.utime;
} }
/// \brief Return the system time of all accumulated interval. /// \brief Return the user time of children of all accumulated interval.
///
/// Any time interval that has been start()ed but not stop()ed
/// will not be accounted for.
clock_t
cutime() const
{
return total_.cutime;
}
/// \brief Return the system time of the current process (whithout children)
/// of all accumulated interval.
/// ///
/// Any time interval that has been start()ed but not stop()ed /// Any time interval that has been start()ed but not stop()ed
/// will not be accounted for. /// will not be accounted for.
@ -139,6 +158,34 @@ namespace spot
return total_.stime; return total_.stime;
} }
/// \brief Return the system time of children of all accumulated interval.
///
/// Any time interval that has been start()ed but not stop()ed
/// will not be accounted for.
clock_t
cstime() const
{
return total_.cstime;
}
clock_t get_uscp(bool user, bool system, bool children, bool parent) const
{
clock_t res = 0;
if (user && parent)
res += utime();
if (user && children)
res += cutime();
if (system && parent)
res += stime();
if (system && children)
res += cstime();
return res;
}
/// \brief Whether the timer is running. /// \brief Whether the timer is running.
bool bool
@ -153,6 +200,10 @@ namespace spot
bool running; bool running;
}; };
// This function declared here must be implemented in each file
// that includes this header, well, only if this operator is needed!
inline std::ostream& operator<<(std::ostream& os, const timer& dt);
/// \brief A map of timer, where each timer has a name. /// \brief A map of timer, where each timer has a name.
/// ///
/// Timer_map also keeps track of the number of measures each timer /// Timer_map also keeps track of the number of measures each timer

View file

@ -794,8 +794,10 @@ namespace spot
} }
out << ',' out << ','
<< s.first << ',' << s.second << ',' << s.first << ',' << s.second << ','
<< te.utime() << ',' << te.stime() << ',' << te.utime() + te.cutime() << ','
<< ts.utime() << ',' << ts.stime() << '\n'; << te.stime() + te.cstime() << ','
<< ts.utime() + ts.cutime() << ','
<< ts.stime() + ts.cstime() << '\n';
} }
static bool show = getenv("SPOT_SATSHOW"); static bool show = getenv("SPOT_SATSHOW");
if (show && res) if (show && res)

View file

@ -1173,8 +1173,10 @@ namespace spot
} }
out << ',' out << ','
<< s.first << ',' << s.second << ',' << s.first << ',' << s.second << ','
<< te.utime() << ',' << te.stime() << ',' << te.utime() + te.cutime() << ','
<< ts.utime() << ',' << ts.stime() << '\n'; << te.stime() + te.cstime() << ','
<< ts.utime() + ts.cutime() << ','
<< ts.stime() + ts.cstime() << '\n';
} }
static bool show = getenv("SPOT_SATSHOW"); static bool show = getenv("SPOT_SATSHOW");
if (show && res) if (show && res)