40 #include "Teuchos_StackedTimer.hpp"
52 level_(std::numeric_limits<unsigned>::max()),name_(
"INVALID"),parent_(nullptr)
63 for (
unsigned i=0; i<level_; ++i)
65 os << name_<<
":"<<
accumulatedTime()<<
" [" << count_started_<<
"] ("<< count_updates_ <<
")"<<std::endl;
67 for (
size_t i=0; i<sub_timers_.size(); ++i) {
68 t_total += sub_timers_[i].accumulatedTime();
69 sub_timers_[i].report(os);
71 if ( sub_timers_.size() == 0 )
73 for (
unsigned i=0; i<=level_; ++i)
82 if (get_full_name() == name) {
86 for (
unsigned i=0;i<sub_timers_.size(); ++i){
87 t = sub_timers_[i].findBaseTimer(name);
97 BaseTimer::TimeInfo t;
98 auto full_name = get_full_name();
99 if (full_name.size() > name.size())
101 if ( strncmp(full_name.c_str(), name.c_str(), full_name.size()))
103 if (get_full_name() == name) {
104 t = BaseTimer::TimeInfo(
this);
108 for (
unsigned i=0;i<sub_timers_.size(); ++i){
109 t = sub_timers_[i].findTimer(name,found);
120 flat_names_.
resize(num_timers);
122 timer_.addTimerNames(flat_names_, pos);
129 flat_names_ = all_names;
135 int num_names = flat_names_.
size();
138 updates_.
resize(num_names);
139 active_.
resize(num_names);
141 if (options.output_minmax || options.output_histogram || options.output_proc_minmax) {
144 if ( options.output_minmax )
145 sum_sq_.
resize(num_names);
148 if (options.output_proc_minmax) {
149 procmin_.
resize(num_names);
150 procmax_.
resize(num_names);
154 if (options.output_histogram ) {
155 hist_.resize(options.num_histogram);
156 for (
int i=0;i<options.num_histogram ; ++i)
157 hist_[i].resize(num_names);
164 if (options.output_total_updates)
165 updates.
resize(num_names);
169 if (options.output_histogram)
173 for (
int i=0;i<num_names; ++i) {
178 used[i] = t.count==0? 0:1;
179 if (options.output_total_updates)
180 updates[i] = t.updates;
190 for (
int i=0;i<num_names;++i)
194 for (
int i=0;i<num_names;++i)
197 if (procmin_.
size()) {
200 int commRank = comm->getRank();
201 for (
int i=0;i<num_names; ++i) {
202 if (used[i] && (min_[i]==time[i]))
203 procmin[i] = commRank;
206 if (used[i] && (max_[i]==time[i]))
207 procmax[i] = commRank;
216 if (options.output_histogram) {
217 for (
int i=0;i<num_names; ++i) {
219 double dh = (max_[i]-min_[i])/options.num_histogram;
223 int bin=(time[i]- min_[i])/dh;
224 bins[i] = std::max(std::min(bin,options.num_histogram-1) , 0);
229 for (
int j=0; j<options.num_histogram; ++j){
230 for (
int i=0;i<num_names; ++i) {
240 if (sum_sq_.
size()) {
241 for (
int i=0;i<num_names; ++i)
248 std::pair<std::string, std::string> getPrefix(
const std::string &name) {
249 for (std::size_t i=name.size()-1; i>0; --i)
250 if (name[i] ==
'@') {
251 return std::pair<std::string, std::string>(name.substr(0,i), name.substr(i+1));
253 return std::pair<std::string, std::string>(std::string(
""), name);
259 std::vector<bool> &printed,
265 double total_time = 0.0;
267 for (
int i=0; i<flat_names_.
size(); ++i ) {
268 if (sum_[i]/active_[i] <= options.drop_time)
272 int level = std::count(flat_names_[i].begin(), flat_names_[i].end(),
'@');
273 if ( (level != print_level) || (level >= options.max_levels) )
275 auto split_names = getPrefix(flat_names_[i]);
276 if ( prefix != split_names.first)
281 std::ostringstream os;
282 for (
int l=0; l<level; ++l)
285 os << split_names.second <<
": ";
286 alignments_.timer_names_= std::max(alignments_.timer_names_,os.str().size());
291 std::ostringstream os;
292 os << sum_[i]/active_[i];
293 alignments_.average_time_ = std::max(alignments_.average_time_,os.str().size());
297 if ( options.output_fraction && parent_time>0) {
298 std::ostringstream os;
299 os <<
" - "<<sum_[i]/active_[i]/parent_time*100<<
"%";
300 alignments_.fraction_ = std::max(alignments_.fraction_,os.str().size());
305 std::ostringstream os;
306 os <<
" ["<<count_[i]/active_[i]<<
"]";
307 alignments_.count_ = std::max(alignments_.count_,os.str().size());
311 if ( options.output_total_updates) {
312 std::ostringstream os;
313 os <<
" ("<<updates_[i]/active_[i]<<
")";
314 alignments_.total_updates_ = std::max(alignments_.total_updates_,os.str().size());
318 if ( options.output_minmax && active_[i]>1) {
320 std::ostringstream os;
321 os <<
" {min=" << min_[i];
322 alignments_.min_ = std::max(alignments_.min_,os.str().size());
325 std::ostringstream os;
326 os <<
", max=" << max_[i];
329 alignments_.max_ = std::max(alignments_.max_,os.str().size());
331 if (procmin_.
size()) {
332 std::ostringstream os;
333 os <<
", proc min=" << procmin_[i];
336 alignments_.procmin_ = std::min(alignments_.procmin_,os.str().size());
338 if (procmax_.
size()) {
339 std::ostringstream os;
340 os <<
", proc max=" << procmax_[i];
343 alignments_.procmax_ = std::max(alignments_.procmax_,os.str().size());
346 std::ostringstream os;
347 os <<
", std dev=" << sqrt(std::max<double>(sum_sq_[i]-sum_[i]*sum_[i]/active_[i],0.0)/(active_[i]-1));
349 alignments_.stddev_ = std::max(alignments_.stddev_,os.str().size());
353 if ( options.output_histogram && active_[i] >1 ) {
354 std::ostringstream os;
356 for (
int h=0;h<options.num_histogram; ++h) {
358 os <<
", "<<hist_[h][i];
363 alignments_.histogram_ = std::max(alignments_.histogram_,os.str().size());
371 if (options.print_names_before_values) {
372 std::ostringstream tmp;
373 for (
int l=0; l<=level; ++l)
375 tmp <<
"Remainder: ";
376 alignments_.timer_names_ = std::max(alignments_.timer_names_,tmp.str().size());
379 std::ostringstream tmp;
380 tmp << sum_[i]/active_[i]- sub_time;
381 alignments_.average_time_ = std::max(alignments_.average_time_,tmp.str().size());
383 if ( options.output_fraction && (sum_[i]/active_[i] > 0.) ) {
384 std::ostringstream tmp;
385 tmp <<
" - "<< (sum_[i]/active_[i]- sub_time)/(sum_[i]/active_[i])*100 <<
"%";
386 alignments_.fraction_ = std::max(alignments_.fraction_,tmp.str().size());
390 total_time += sum_[i]/active_[i];
403 double total_time = 0.0;
405 for (
int i=0; i<flat_names_.
size(); ++i ) {
406 if (sum_[i]/active_[i] <= options.drop_time) {
411 int level = std::count(flat_names_[i].begin(), flat_names_[i].end(),
'@');
412 if ( (level != print_level) || (level >= options.max_levels) )
414 auto split_names = getPrefix(flat_names_[i]);
415 if ( prefix != split_names.first)
419 if (options.print_names_before_values) {
420 std::ostringstream tmp;
421 for (
int l=0; l<level; ++l) {
425 tmp << split_names.second <<
": ";
426 if (options.align_columns)
427 os << std::left << std::setw(alignments_.timer_names_);
432 std::ostringstream tmp;
433 tmp << sum_[i]/active_[i];
434 if (options.align_columns)
435 os << std::left << std::setw(alignments_.average_time_);
439 if ( options.output_fraction && parent_time>0) {
440 std::ostringstream tmp;
441 tmp <<
" - "<<sum_[i]/active_[i]/parent_time*100<<
"%";
442 if (options.align_columns)
443 os << std::left << std::setw(alignments_.fraction_);
447 else if (options.output_fraction) {
448 if (options.align_columns)
449 os << std::setw(alignments_.fraction_) <<
" ";
453 std::ostringstream tmp;
454 tmp <<
" ["<<count_[i]/active_[i]<<
"]";
455 if (options.align_columns)
456 os << std::left << std::setw(alignments_.count_);
460 if ( options.output_total_updates ) {
461 std::ostringstream tmp;
462 tmp <<
" ("<<updates_[i]/active_[i]<<
")";
463 if (options.align_columns)
464 os << std::left << std::setw(alignments_.total_updates_);
468 if ( options.output_minmax && active_[i]>1) {
470 std::ostringstream tmp;
471 tmp <<
" {min="<<min_[i];
472 if (options.align_columns)
473 os << std::left << std::setw(alignments_.min_);
477 std::ostringstream tmp;
478 tmp <<
", max="<<max_[i];
481 if (options.align_columns)
482 os << std::left << std::setw(alignments_.max_);
485 if (procmin_.
size()) {
486 std::ostringstream tmp;
487 tmp <<
", proc min="<<procmin_[i];
490 if (options.align_columns)
491 os << std::left << std::setw(alignments_.procmin_);
494 if (procmax_.
size()) {
495 std::ostringstream tmp;
496 tmp <<
", proc max="<<procmax_[i];
499 if (options.align_columns)
500 os << std::left << std::setw(alignments_.procmax_);
504 std::ostringstream tmp;
505 tmp <<
", std dev="<<sqrt(std::max<double>(sum_sq_[i]-sum_[i]*sum_[i]/active_[i],0.0)/(active_[i]-1));
507 if (options.align_columns)
508 os << std::left << std::setw(alignments_.stddev_);
512 else if ( options.output_minmax) {
514 size_t offset = alignments_.min_ + alignments_.max_ + alignments_.stddev_;
515 for (
size_t j=0; j < offset; ++j)
520 if ( options.output_histogram && active_[i] >1 ) {
521 std::ostringstream tmp;
523 for (
int h=0;h<options.num_histogram; ++h) {
525 tmp <<
", "<<hist_[h][i];
530 if (options.align_columns)
531 os << std::left << std::setw(alignments_.histogram_);
534 else if ( options.output_histogram) {
536 for (
size_t j=0; j < alignments_.histogram_; ++j)
540 if (! options.print_names_before_values) {
541 std::ostringstream tmp;
543 for (
int l=0; l<level; ++l) {
547 tmp << split_names.second <<
": ";
553 double sub_time =
printLevel(flat_names_[i], level+1, os, printed, sum_[i]/active_[i], options);
557 if (options.print_names_before_values) {
558 std::ostringstream tmp;
559 for (
int l=0; l<=level; ++l)
561 tmp <<
"Remainder: ";
562 if (options.align_columns)
563 os << std::left << std::setw(alignments_.timer_names_);
567 std::ostringstream tmp;
568 tmp << sum_[i]/active_[i]- sub_time;
569 if (options.align_columns)
570 os << std::left << std::setw(alignments_.average_time_);
573 if ( options.output_fraction && (sum_[i]/active_[i] > 0.) ) {
574 if (options.align_columns)
575 os << std::left << std::setw(alignments_.fraction_);
576 std::ostringstream tmp;
577 tmp <<
" - "<< (sum_[i]/active_[i]- sub_time)/(sum_[i]/active_[i])*100 <<
"%";
580 if (! options.print_names_before_values) {
583 offset += alignments_.count_;
584 if (options.output_total_updates)
585 offset += alignments_.total_updates_;
586 if (options.output_minmax)
587 offset += alignments_.min_ + alignments_.max_ + alignments_.stddev_;
588 if (options.output_histogram)
589 offset += alignments_.histogram_;
590 for (
size_t j=0; j < offset; ++j)
593 std::ostringstream tmp;
595 for (
int l=0; l<=level; ++l)
597 tmp <<
"Remainder: ";
598 if (options.align_columns)
599 os << std::left << std::setw(alignments_.timer_names_);
604 total_time += sum_[i]/active_[i];
609 static void printXMLEscapedString(std::ostream& os,
const std::string& str)
637 StackedTimer::printLevelXML (std::string prefix,
int print_level, std::ostream& os, std::vector<bool> &printed,
double parent_time,
const std::string& rootName)
639 constexpr
int indSpaces = 2;
640 int indent = indSpaces * print_level;
642 double total_time = 0.0;
644 for (
int i=0; i<flat_names_.
size(); ++i) {
647 int level = std::count(flat_names_[i].begin(), flat_names_[i].end(),
'@');
648 if ( level != print_level)
650 auto split_names = getPrefix(flat_names_[i]);
651 if ( prefix != split_names.first)
654 for (
int j = 0; j < indent; j++)
656 os <<
"<timing name=\"";
657 if(level == 0 && rootName.length())
658 printXMLEscapedString(os, rootName);
660 printXMLEscapedString(os, split_names.second);
661 os <<
"\" value=\"" << sum_[i]/active_[i] <<
"\"";
665 std::ostringstream osInner;
666 double sub_time =
printLevelXML(flat_names_[i], print_level+1, osInner, printed, sum_[i]/active_[i]);
667 std::string innerContents = osInner.str();
668 if(innerContents.length())
674 for (
int j = 0; j < indent + indSpaces; j++)
676 os <<
"<timing name=\"Remainder\" value=\"" << (sum_[i]/active_[i] - sub_time) <<
"\"/>\n";
679 for (
int j = 0; j < indent; j++)
688 total_time += sum_[i]/active_[i];
698 if (rank(*comm) == 0 ) {
699 if (options.print_warnings) {
700 os <<
"*** Teuchos::StackedTimer::report() - Remainder for a level will be ***"
701 <<
"\n*** incorrect if a timer in the level does not exist on every rank ***"
702 <<
"\n*** of the MPI Communicator. ***"
705 if ( (options.max_levels != INT_MAX) && options.print_warnings) {
706 os <<
"Teuchos::StackedTimer::report() - max_levels manually set to " << options.max_levels
707 <<
". \nTo print more levels, increase value of OutputOptions::max_levels." << std::endl;
709 if ( (! options.print_names_before_values) && (! options.align_columns)) {
710 options.align_columns =
true;
711 if (options.print_warnings)
712 os <<
"Teuchos::StackedTimer::report() - option print_names_before_values=false "
713 <<
"\nrequires that the option align_columns=true too. Setting the value for "
714 <<
"\nalign_column to true."
717 if (options.align_columns) {
718 std::vector<bool> printed(flat_names_.
size(),
false);
722 std::vector<bool> printed(flat_names_.
size(),
false);
734 if (rank(*comm) == 0 ) {
735 std::vector<bool> printed(flat_names_.
size(),
false);
736 os <<
"<?xml version=\"1.0\"?>\n";
737 os <<
"<performance-report date=\"" << timestamp <<
"\" name=\"nightly_run_" << datestamp <<
"\" time-units=\"seconds\">\n";
739 os <<
"</performance-report>\n";
745 const char* rawWatchrDir = getenv(
"WATCHR_PERF_DIR");
746 const char* rawBuildName = getenv(
"WATCHR_BUILD_NAME");
750 std::string watchrDir = rawWatchrDir;
751 if(!watchrDir.length())
757 std::string buildName = rawBuildName ? rawBuildName :
"";
758 std::string datestamp;
759 std::string timestamp;
765 tstruct = gmtime(&t);
766 strftime(buf, 256,
"%Y_%m_%d", tstruct);
768 strftime(buf, 256,
"%FT%H:%M:%S", tstruct);
775 std::string fullFile;
777 if(rank(*comm) == 0) {
778 std::string nameNoSpaces = name;
779 for(
char& c : nameNoSpaces)
784 if(buildName.length())
787 std::string buildNameNoSpaces = buildName;
788 for(
char& c : buildNameNoSpaces)
793 fullFile = watchrDir +
'/' + buildNameNoSpaces +
"-" + nameNoSpaces +
'_' + datestamp +
".xml";
796 fullFile = watchrDir +
'/' + nameNoSpaces +
'_' + datestamp +
".xml";
797 std::ofstream os(fullFile);
798 std::vector<bool> printed(flat_names_.
size(),
false);
799 os <<
"<?xml version=\"1.0\"?>\n";
800 os <<
"<performance-report date=\"" << timestamp <<
"\" name=\"nightly_run_" << datestamp <<
"\" time-units=\"seconds\">\n";
801 printLevelXML(
"", 0, os, printed, 0.0, buildName +
": " + name);
802 os <<
"</performance-report>\n";
807 void StackedTimer::enableVerbose(
const bool enable_verbose)
810 void StackedTimer::enableVerboseTimestamps(
const unsigned levels)
void merge(Teuchos::RCP< const Teuchos::Comm< int > > comm)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
bool enable_verbose_
If set to true, prints to the debug ostream. At construction, default value is set from environment v...
T * getRawPtr()
Return a raw pointer to beginning of array or NULL if unsized.
double printLevelXML(std::string prefix, int level, std::ostream &os, std::vector< bool > &printed, double parent_time, const std::string &rootName="")
std::string reportWatchrXML(const std::string &name, Teuchos::RCP< const Teuchos::Comm< int > > comm)
unsigned verbose_timestamp_levels_
If set to a value greater than 0, verbose mode will print that many levels of timers with timestamps...
BaseTimer::TimeInfo findTimer(const std::string &name, bool &found)
double printLevel(std::string prefix, int level, std::ostream &os, std::vector< bool > &printed, double parent_time, const OutputOptions &options)
double accumulatedTime(const std::string &name="")
void report(std::ostream &os)
the basic timer used elsewhere, uses MPI_Wtime for time
double computeColumnWidthsForAligment(std::string prefix, int print_level, std::vector< bool > &printed, double parent_time, const OutputOptions &options)
void reportXML(std::ostream &os, const std::string &datestamp, const std::string ×tamp, Teuchos::RCP< const Teuchos::Comm< int > > comm)
void collectRemoteData(Teuchos::RCP< const Teuchos::Comm< int > > comm, const OutputOptions &options)
void mergeCounterNames(const Comm< int > &comm, const Array< std::string > &localNames, Array< std::string > &globalNames, const ECounterSetOp setOp)
Merge counter names over all processors.
void resize(size_type new_size, const value_type &x=value_type())
Teuchos::RCP< std::ostream > verbose_ostream_
For debugging, this is the ostream used for printing.
LevelTimer timer_
Base timer.
void error_out(const std::string &msg, const bool)
Error reporting function for stacked timer.
LevelTimer()
Default constructor, shouldn't be used but needed for std::vector.
const BaseTimer * findBaseTimer(const std::string &name) const
Smart reference counting pointer class for automatic garbage collection.