18 #include "libmesh/perf_log.h" 21 #include "libmesh/int_range.h" 22 #include "libmesh/timestamp.h" 30 #ifdef LIBMESH_HAVE_UNISTD_H 33 #include <sys/types.h> 37 #ifdef LIBMESH_HAVE_SYS_UTSNAME_H 38 #include <sys/utsname.h> 41 #ifdef LIBMESH_HAVE_PWD_H 57 label_name(
std::move(ln)),
59 summarize_logs(false),
84 libmesh_error_msg_if(pos.second.open,
85 "ERROR clearing performance log for class " 89 <<
" is still being monitored!");
103 const std::string & header)
108 #ifdef LIBMESH_HAVE_OPENMP 111 libmesh_assert_equal_to(omp_get_num_threads(), 1);
114 const char * label_c_str;
115 const char * header_c_str;
119 label_c_str = label_it->second.get();
122 const std::size_t labelsizep1 = label.size()+1;
123 auto newcopy = std::make_unique<char[]>(labelsizep1);
124 std::strncpy(newcopy.get(), label.c_str(), labelsizep1);
125 label_c_str = newcopy.get();
131 header_c_str = header_it->second.get();
134 const std::size_t headersizep1 = header.size()+1;
135 auto newcopy = std::make_unique<char[]>(headersizep1);
136 std::strncpy(newcopy.get(), header.c_str(), headersizep1);
137 header_c_str = newcopy.get();
142 this->
fast_push(label_c_str, header_c_str);
150 this->
push(std::string(label), std::string(header));
158 const std::string & header)
163 #ifdef LIBMESH_HAVE_OPENMP 166 libmesh_exceptionless_assert(omp_get_num_threads() == 1);
180 this->
fast_pop(label_c_str, header_c_str);
188 this->
pop(std::string(label), std::string(header));
195 std::ostringstream oss;
201 #ifdef LIBMESH_HAVE_SYS_UTSNAME_H 203 struct utsname sysInfo;
217 #ifdef LIBMESH_HAVE_GETPWUID 218 struct passwd * p = getpwuid(getuid());
236 std::vector<std::ostringstream*> v;
237 v.push_back(&pid_stream);
238 v.push_back(&nprocs_stream);
239 v.push_back(&time_stream);
240 v.push_back(&os_stream);
241 v.push_back(&host_stream);
242 v.push_back(&osrel_stream);
243 v.push_back(&osver_stream);
244 v.push_back(&machine_stream);
245 v.push_back(&user_stream);
254 time_stream <<
"| Time: ";
255 os_stream <<
"| OS: ";
256 host_stream <<
"| HostName: ";
257 osrel_stream <<
"| OS Release: ";
258 osver_stream <<
"| OS Version: ";
259 machine_stream <<
"| Machine: ";
262 #ifdef LIBMESH_HAVE_SYS_UTSNAME_H 263 os_stream << sysInfo.sysname ;
264 host_stream << sysInfo.nodename ;
265 osrel_stream << sysInfo.release ;
266 osver_stream << sysInfo.version ;
267 machine_stream << sysInfo.machine ;
269 os_stream <<
"Unknown";
270 host_stream <<
"Unknown";
271 osrel_stream <<
"Unknown";
272 osver_stream <<
"Unknown";
273 machine_stream <<
"Unknown";
276 user_stream <<
"| Username: ";
277 #ifdef LIBMESH_HAVE_GETPWUID 279 user_stream << p->pw_name;
282 user_stream <<
"Unknown";
285 std::string libmesh_configure_info(LIBMESH_CONFIGURE_INFO);
286 std::vector<std::string> parsed_libmesh_configure_info;
288 parsed_libmesh_configure_info);
293 libmesh_assert_greater (parsed_libmesh_configure_info.size(), 0);
296 unsigned int max_length = 0;
298 if (v_i->str().size() > max_length)
299 max_length = cast_int<unsigned int>
303 for (
auto & plci_i : parsed_libmesh_configure_info)
304 if (plci_i.size() > max_length)
305 max_length = cast_int<unsigned int> (plci_i.size());
309 << std::string(max_length+1,
'-')
315 if (v_i->str().size())
317 << std::setw (cast_int<int>
318 (max_length + 4 - v_i->str().size()))
326 oss <<
"| Configuration: " 327 << parsed_libmesh_configure_info[0]
328 << std::setw (cast_int<int>
330 parsed_libmesh_configure_info[0].size() - 18))
339 << parsed_libmesh_configure_info[i]
340 << std::setw (cast_int<int>
342 parsed_libmesh_configure_info[i].size() - 3))
350 << std::string(max_length+1,
'-')
362 std::ostringstream oss;
377 unsigned int event_col_width = 30;
378 const unsigned int ncalls_col_width = 11;
379 const unsigned int tot_time_col_width = 12;
380 const unsigned int avg_time_col_width = 12;
381 const unsigned int tot_time_incl_sub_col_width = 12;
382 const unsigned int avg_time_incl_sub_col_width = 12;
383 const unsigned int pct_active_col_width = 9;
384 const unsigned int pct_active_incl_sub_col_width = 9;
389 if (std::strlen(pos.first.second)+3 > event_col_width)
390 event_col_width = cast_int<unsigned int>
391 (std::strlen(pos.first.second)+3);
394 const unsigned int total_col_width =
399 tot_time_incl_sub_col_width +
400 avg_time_incl_sub_col_width +
401 pct_active_col_width+
402 pct_active_incl_sub_col_width+1;
406 << std::string(total_col_width,
'-')
411 std::ostringstream temp;
412 temp <<
"| " <<
label_name <<
" Performance: Alive time=" << elapsed_time
416 const unsigned int temp_size = cast_int<unsigned int>
426 if (temp_size < total_col_width+2)
427 oss << std::setw(total_col_width - temp_size + 2)
436 << std::string(total_col_width,
'-')
442 << std::setw(event_col_width)
445 << std::setw(ncalls_col_width)
448 << std::setw(tot_time_col_width)
451 << std::setw(avg_time_col_width)
454 << std::setw(tot_time_incl_sub_col_width)
457 << std::setw(avg_time_incl_sub_col_width)
460 << std::setw(pct_active_col_width+pct_active_incl_sub_col_width)
462 <<
"% of Active Time" 465 << std::setw(event_col_width)
468 << std::setw(ncalls_col_width)
471 << std::setw(tot_time_col_width)
474 << std::setw(avg_time_col_width)
477 << std::setw(tot_time_incl_sub_col_width)
480 << std::setw(avg_time_incl_sub_col_width)
483 << std::setw(pct_active_col_width)
486 << std::setw(pct_active_incl_sub_col_width)
490 << std::string(total_col_width,
'-')
492 << std::string(total_col_width,
' ')
495 unsigned int summed_function_calls = 0;
496 double summed_total_time = 0;
497 double summed_percentage = 0;
499 std::string last_header(
"");
502 std::map<std::pair<std::string, std::string>,
PerfData> string_log;
504 for (
auto char_data :
log)
507 string_log[std::make_pair(std::string(), char_data.first.first)] +=
512 string_log[std::make_pair(char_data.first.first,
513 char_data.first.second)] =
517 for (
auto pos : string_log)
519 const PerfData & perf_data = pos.second;
522 if (perf_data.
count != 0)
524 const unsigned int perf_count = perf_data.
count;
525 const double perf_time = perf_data.
tot_time;
526 const double perf_avg_time = perf_time /
static_cast<double>(perf_count);
528 const double perf_avg_time_incl_sub = perf_time_incl_sub /
static_cast<double>(perf_count);
530 const double perf_percent_incl_sub = (
total_time != 0.) ? perf_time_incl_sub /
total_time * 100. : 0.;
532 summed_function_calls += perf_count;
533 summed_total_time += perf_time;
534 summed_percentage += perf_percent;
537 if (pos.first.first ==
"")
539 << std::setw(event_col_width)
545 if (last_header != pos.first.first)
547 last_header = pos.first.first;
553 << std::string(total_col_width,
' ')
555 << std::setw(total_col_width-1)
562 << std::setw(event_col_width-2)
569 oss << std::setw(ncalls_col_width)
573 std::ios_base::fmtflags out_flags = oss.flags();
577 << std::setprecision(4)
578 << std::setw(tot_time_col_width)
585 << std::setprecision(6)
586 << std::setw(avg_time_col_width)
592 << std::setprecision(4)
593 << std::setw(tot_time_incl_sub_col_width)
595 << perf_time_incl_sub;
599 << std::setprecision(6)
600 << std::setw(avg_time_incl_sub_col_width)
602 << perf_avg_time_incl_sub;
606 << std::setprecision(2)
607 << std::setw(pct_active_col_width)
613 << std::setprecision(2)
614 << std::setw(pct_active_incl_sub_col_width)
616 << perf_percent_incl_sub;
619 oss.flags(out_flags);
626 << std::string(total_col_width,
'-')
628 << std::setw(event_col_width)
635 if (summed_function_calls < 9999999)
636 oss << std::setw(ncalls_col_width)
637 << summed_function_calls;
642 std::ios_base::fmtflags out_flags = oss.flags();
644 oss << std::scientific
645 << std::setprecision(3)
646 << std::setw(ncalls_col_width)
648 <<
static_cast<Real>(summed_function_calls);
651 oss.flags(out_flags);
657 << std::setprecision(4)
658 << std::setw(tot_time_col_width)
660 << summed_total_time;
663 oss << std::setw(avg_time_col_width) <<
"";
666 oss << std::setw(tot_time_incl_sub_col_width)
668 << std::setw(avg_time_incl_sub_col_width)
673 << std::setprecision(2)
674 << std::setw(pct_active_col_width)
677 << std::setw(pct_active_incl_sub_col_width)
680 << std::string(total_col_width,
'-')
690 std::ostringstream oss;
720 std::string log_string = this->
get_log();
721 if (log_string.size() > 0)
733 return log[std::make_pair(header_c_str, label_c_str)];
736 auto iter = std::find_if
738 [&label, &header] (log_type::const_reference a)
741 !std::strcmp(header.c_str(), a.first.first) &&
742 !std::strcmp(label.c_str(), a.first.second);
751 const std::string & header)
753 this->
push(label,header);
759 const std::string & header)
761 this->
pop(label,header);
790 const std::string split_on(
"' '");
792 size_t current_pos = 0;
796 if (
size_t end_pos = input.find(split_on, current_pos);
797 end_pos != std::string::npos)
801 output.push_back( input.substr(current_pos, end_pos - current_pos + 1) );
805 current_pos = end_pos + split_on.size() - 1;
813 output.push_back( input.substr(current_pos) );
double tot_time_incl_sub
Total time spent in this event, including sub-events.
void pop(const char *label, const char *header="")
Pop the event label off the stack, resuming any lower event.
PerfLog(std::string label_name="", const bool log_events=true)
Constructor.
processor_id_type global_n_processors()
void fast_push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
std::string get_timestamp()
The PerfData class simply contains the performance data that is recorded for individual events...
bool log_events
Flag to optionally disable all logging.
int gettimeofday(struct timeval *tp, struct timezone *tzp)
double total_time
The total running time for recorded events.
void stop_event(const std::string &label, const std::string &header="")
Stop monitoring the event named label.
log_type log
The actual log.
The libMesh namespace provides an interface to certain functionality in the library.
void fast_pop(const char *label, const char *header="") noexcept
Pop the event label off the stack, resuming any lower event.
std::stack< PerfData * > log_stack
A stack to hold the current performance log trace.
bool summarize_logs
Flag to optionally summarize logs.
PerfData get_perf_data(const std::string &label, const std::string &header="")
Return the PerfData object associated with a label and header.
std::string get_perf_info() const
const std::string label_name
The label for this object.
std::string get_log() const
std::string get_info_header() const
void push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
void restart_event(const std::string &label, const std::string &header="")
Restart monitoring the event.
void split_on_whitespace(const std::string &input, std::vector< std::string > &output) const
Splits a string on whitespace into a vector of separate strings.
void clear()
Clears all the internal data and restores the data structures to a pristine state.
double tot_time
Total time spent in this event.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
int active_threads
An integer which is set to the number of active threads when we are in a Threads:: parallel operation...
processor_id_type global_processor_id()
void print_log() const
Print the log.
void pause_event(const std::string &label, const std::string &header="")
Suspend monitoring of the event.
unsigned int count
The number of times this event has been executed.
struct timeval tstart
The time we were constructed or last cleared.
static bool called
Flag indicating if print_log() has been called.
std::map< std::string, std::unique_ptr< const char[]> > non_temporary_strings
Workaround to give us fixed pointers to character arrays for every string.
void start_event(const std::string &label, const std::string &header="")
Start monitoring the event named label.