libMesh
perf_log.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 #include "libmesh/perf_log.h"
19 
20 // Local includes
21 #include "libmesh/int_range.h"
22 #include "libmesh/timestamp.h"
23 
24 // C++ includes
25 #include <algorithm>
26 #include <iostream>
27 #include <iomanip>
28 #include <cstring>
29 #include <ctime>
30 #ifdef LIBMESH_HAVE_UNISTD_H
31 #include <unistd.h> // for getuid()
32 #endif
33 #include <sys/types.h>
34 #include <vector>
35 #include <sstream>
36 
37 #ifdef LIBMESH_HAVE_SYS_UTSNAME_H
38 #include <sys/utsname.h>
39 #endif
40 
41 #ifdef LIBMESH_HAVE_PWD_H
42 #include <pwd.h>
43 #endif
44 
45 namespace libMesh
46 {
47 
48 
49 // ------------------------------------------------------------
50 // PerfLog class member functions
51 
52 bool PerfLog::called = false;
53 
54 
55 PerfLog::PerfLog(std::string ln,
56  const bool le) :
57  label_name(std::move(ln)),
58  log_events(le),
59  summarize_logs(false),
60  total_time(0.)
61 {
62  gettimeofday (&tstart, nullptr);
63 
64  if (log_events)
65  this->clear();
66 }
67 
68 
69 
71 {
72  if (log_events)
73  this->print_log();
74 }
75 
76 
77 
79 {
80  if (log_events)
81  {
82  // check that all events are closed
83  for (auto pos : log)
84  libmesh_error_msg_if(pos.second.open,
85  "ERROR clearing performance log for class "
86  << label_name
87  << "\nevent "
88  << pos.first.second
89  << " is still being monitored!");
90 
91  gettimeofday (&tstart, nullptr);
92 
93  log.clear();
94 
95  while (!log_stack.empty())
96  log_stack.pop();
97  }
98 }
99 
100 
101 
102 void PerfLog::push (const std::string & label,
103  const std::string & header)
104 {
105  const char * label_c_str;
106  const char * header_c_str;
107 
108  if (const auto label_it = non_temporary_strings.find(label);
109  label_it != non_temporary_strings.end())
110  label_c_str = label_it->second.get();
111  else
112  {
113  const std::size_t labelsizep1 = label.size()+1;
114  auto newcopy = std::make_unique<char[]>(labelsizep1);
115  std::strncpy(newcopy.get(), label.c_str(), labelsizep1);
116  label_c_str = newcopy.get();
117  non_temporary_strings[label] = std::move(newcopy);
118  }
119 
120  if (const auto header_it = non_temporary_strings.find(header);
121  header_it != non_temporary_strings.end())
122  header_c_str = header_it->second.get();
123  else
124  {
125  const std::size_t headersizep1 = header.size()+1;
126  auto newcopy = std::make_unique<char[]>(headersizep1);
127  std::strncpy(newcopy.get(), header.c_str(), headersizep1);
128  header_c_str = newcopy.get();
129  non_temporary_strings[header] = std::move(newcopy);
130  }
131 
132  if (this->log_events)
133  this->fast_push(label_c_str, header_c_str);
134 }
135 
136 
137 
138 void PerfLog::push (const char * label,
139  const char * header)
140 {
141  this->push(std::string(label), std::string(header));
142 }
143 
144 
145 
146 
147 
148 void PerfLog::pop (const std::string & label,
149  const std::string & header)
150 {
151 
152  const char * label_c_str = non_temporary_strings[label].get();
153  const char * header_c_str = non_temporary_strings[header].get();
154 
155  // This could happen if users are *mixing* string and char* APIs for
156  // the same label/header combination. For perfect backwards
157  // compatibility we should handle that, but there's just no fast way
158  // to do so.
159  libmesh_assert(label_c_str);
160  libmesh_assert(header_c_str);
161 
162  if (this->log_events)
163  this->fast_pop(label_c_str, header_c_str);
164 }
165 
166 
167 
168 void PerfLog::pop (const char * label,
169  const char * header)
170 {
171  this->pop(std::string(label), std::string(header));
172 }
173 
174 
175 
176 std::string PerfLog::get_info_header() const
177 {
178  std::ostringstream oss;
179 
180  if (log_events)
181  {
182  std::string date = Utility::get_timestamp();
183 
184 #ifdef LIBMESH_HAVE_SYS_UTSNAME_H
185  // Get system information
186  struct utsname sysInfo;
187  uname(&sysInfo);
188 #endif
189 
190  // Get user information
191  //
192  // Some systems, for example Crays, actually have getpwuid on the head-node
193  // but (if I understand correctly) a dynamically-linked glibc is not available
194  // on the backend, which is running a reduced operating system like Compute
195  // Node Linux. Thus functions like getpwuid cannot be called. This makes
196  // automatically testing for the existence of getpwuid on the login node
197  // difficult. The configure test would work on the login node but will fail
198  // on the backend. Hence we have added a configure flag, --disable-getpwuid,
199  // to manually turn this off.
200 #ifdef LIBMESH_HAVE_GETPWUID
201  struct passwd * p = getpwuid(getuid());
202 #endif
203  oss << "\n";
204 
205  // Construct string stream objects for each of the outputs
206  std::ostringstream
207  pid_stream,
208  nprocs_stream,
209  time_stream,
210  os_stream,
211  host_stream,
212  osrel_stream,
213  osver_stream,
214  machine_stream,
215  user_stream;
216 
217 
218  // Put pointers to these streams in a vector
219  std::vector<std::ostringstream*> v;
220  v.push_back(&pid_stream);
221  v.push_back(&nprocs_stream);
222  v.push_back(&time_stream);
223  v.push_back(&os_stream);
224  v.push_back(&host_stream);
225  v.push_back(&osrel_stream);
226  v.push_back(&osver_stream);
227  v.push_back(&machine_stream);
228  v.push_back(&user_stream);
229 
230  // Fill string stream objects
232  {
233  pid_stream << "| Processor id: " << libMesh::global_processor_id();
234  nprocs_stream << "| Num Processors: " << libMesh::global_n_processors();
235  }
236 
237  time_stream << "| Time: ";
238  os_stream << "| OS: ";
239  host_stream << "| HostName: ";
240  osrel_stream << "| OS Release: ";
241  osver_stream << "| OS Version: ";
242  machine_stream << "| Machine: ";
243 
244  time_stream << date;
245 #ifdef LIBMESH_HAVE_SYS_UTSNAME_H
246  os_stream << sysInfo.sysname ;
247  host_stream << sysInfo.nodename ;
248  osrel_stream << sysInfo.release ;
249  osver_stream << sysInfo.version ;
250  machine_stream << sysInfo.machine ;
251 #else
252  os_stream << "Unknown";
253  host_stream << "Unknown";
254  osrel_stream << "Unknown";
255  osver_stream << "Unknown";
256  machine_stream << "Unknown";
257 
258 #endif
259  user_stream << "| Username: ";
260 #ifdef LIBMESH_HAVE_GETPWUID
261  if (p && p->pw_name)
262  user_stream << p->pw_name;
263  else
264 #endif
265  user_stream << "Unknown";
266 
267  // Parse the LIBMESH_CONFIGURE_INFO string literal before using it in PerfLog output
268  std::string libmesh_configure_info(LIBMESH_CONFIGURE_INFO);
269  std::vector<std::string> parsed_libmesh_configure_info;
270  this->split_on_whitespace(libmesh_configure_info,
271  parsed_libmesh_configure_info);
272 
273  // There should always be at at least one entry in
274  // parsed_libmesh_configure_info, even if the user just ran
275  // ../configure.
276  libmesh_assert_greater (parsed_libmesh_configure_info.size(), 0);
277 
278  // Find the longest string in all the streams
279  unsigned int max_length = 0;
280  for (auto & v_i : v)
281  if (v_i->str().size() > max_length)
282  max_length = cast_int<unsigned int>
283  (v_i->str().size());
284 
285  // Find the longest string in the parsed_libmesh_configure_info
286  for (auto & plci_i : parsed_libmesh_configure_info)
287  if (plci_i.size() > max_length)
288  max_length = cast_int<unsigned int> (plci_i.size());
289 
290  // Print dashed line for the header
291  oss << ' '
292  << std::string(max_length+1, '-')
293  << '\n';
294 
295  // Loop over all the strings and add end formatting
296  for (auto & v_i : v)
297  {
298  if (v_i->str().size())
299  oss << v_i->str()
300  << std::setw (cast_int<int>
301  (max_length + 4 - v_i->str().size()))
302  << std::right
303  << "|\n";
304  }
305 
306  // Print out configuration header plus first parsed string. The
307  // magic number 18 below accounts for the length of the word
308  // 'Configuration'.
309  oss << "| Configuration: "
310  << parsed_libmesh_configure_info[0]
311  << std::setw (cast_int<int>
312  (max_length + 4 -
313  parsed_libmesh_configure_info[0].size() - 18))
314  << std::right
315  << "|\n";
316 
317  // Loop over the parsed_libmesh_configure_info and add end formatting. The magic
318  // number 3 below accounts for the leading 'pipe' character and indentation
319  for (auto i : IntRange<std::size_t>(1, parsed_libmesh_configure_info.size()))
320  {
321  oss << "| "
322  << parsed_libmesh_configure_info[i]
323  << std::setw (cast_int<int>
324  (max_length + 4 -
325  parsed_libmesh_configure_info[i].size() - 3))
326  << std::right
327  << "|\n";
328  }
329 
330 
331  // Print dashed line
332  oss << ' '
333  << std::string(max_length+1, '-')
334  << '\n';
335  }
336 
337  return oss.str();
338 }
339 
340 
341 
342 
343 std::string PerfLog::get_perf_info() const
344 {
345  std::ostringstream oss;
346 
347  if (!log_events || log.empty())
348  return oss.str();
349 
350  // Stop timing for this event.
351  struct timeval tstop;
352 
353  gettimeofday (&tstop, nullptr);
354 
355  const double elapsed_time = (static_cast<double>(tstop.tv_sec - tstart.tv_sec) +
356  static_cast<double>(tstop.tv_usec - tstart.tv_usec)*1.e-6);
357 
358  // Figure out the formatting required based on the event names
359  // Unsigned ints for each of the column widths
360  unsigned int event_col_width = 30;
361  const unsigned int ncalls_col_width = 11;
362  const unsigned int tot_time_col_width = 12;
363  const unsigned int avg_time_col_width = 12;
364  const unsigned int tot_time_incl_sub_col_width = 12;
365  const unsigned int avg_time_incl_sub_col_width = 12;
366  const unsigned int pct_active_col_width = 9;
367  const unsigned int pct_active_incl_sub_col_width = 9;
368 
369  // Reset the event column width based on the longest event name plus
370  // a possible 2-character indentation, plus a space.
371  for (auto pos : log)
372  if (std::strlen(pos.first.second)+3 > event_col_width)
373  event_col_width = cast_int<unsigned int>
374  (std::strlen(pos.first.second)+3);
375 
376  // Set the total width of the column
377  const unsigned int total_col_width =
378  event_col_width +
379  ncalls_col_width +
380  tot_time_col_width +
381  avg_time_col_width +
382  tot_time_incl_sub_col_width +
383  avg_time_incl_sub_col_width +
384  pct_active_col_width+
385  pct_active_incl_sub_col_width+1;
386 
387  // Print dashed line
388  oss << ' '
389  << std::string(total_col_width, '-')
390  << '\n';
391 
392  {
393  // Construct temporary message string
394  std::ostringstream temp;
395  temp << "| " << label_name << " Performance: Alive time=" << elapsed_time
396  << ", Active time=" << total_time;
397 
398  // Get the size of the temporary string
399  const unsigned int temp_size = cast_int<unsigned int>
400  (temp.str().size());
401 
402  // Send the temporary message to the output
403  oss << temp.str();
404 
405  // If this string is longer than the previously computed total
406  // column width, skip the additional formatting... this shouldn't
407  // happen often, hopefully. Add two additional characters for a
408  // space and a "|" character at the end.
409  if (temp_size < total_col_width+2)
410  oss << std::setw(total_col_width - temp_size + 2)
411  << std::right
412  << "|";
413 
414  oss << '\n';
415  }
416 
417  // Print dashed line
418  oss << ' '
419  << std::string(total_col_width, '-')
420  << '\n';
421 
422 
423  // Write out the header for the events listing
424  oss << "| "
425  << std::setw(event_col_width)
426  << std::left
427  << "Event"
428  << std::setw(ncalls_col_width)
429  << std::left
430  << "nCalls"
431  << std::setw(tot_time_col_width)
432  << std::left
433  << "Total Time"
434  << std::setw(avg_time_col_width)
435  << std::left
436  << "Avg Time"
437  << std::setw(tot_time_incl_sub_col_width)
438  << std::left
439  << "Total Time"
440  << std::setw(avg_time_incl_sub_col_width)
441  << std::left
442  << "Avg Time"
443  << std::setw(pct_active_col_width+pct_active_incl_sub_col_width)
444  << std::left
445  << "% of Active Time"
446  << "|\n"
447  << "| "
448  << std::setw(event_col_width)
449  << std::left
450  << ""
451  << std::setw(ncalls_col_width)
452  << std::left
453  << ""
454  << std::setw(tot_time_col_width)
455  << std::left
456  << "w/o Sub"
457  << std::setw(avg_time_col_width)
458  << std::left
459  << "w/o Sub"
460  << std::setw(tot_time_incl_sub_col_width)
461  << std::left
462  << "With Sub"
463  << std::setw(avg_time_incl_sub_col_width)
464  << std::left
465  << "With Sub"
466  << std::setw(pct_active_col_width)
467  << std::left
468  << "w/o S"
469  << std::setw(pct_active_incl_sub_col_width)
470  << std::left
471  << "With S"
472  << "|\n|"
473  << std::string(total_col_width, '-')
474  << "|\n|"
475  << std::string(total_col_width, ' ')
476  << "|\n";
477 
478  unsigned int summed_function_calls = 0;
479  double summed_total_time = 0;
480  double summed_percentage = 0;
481 
482  std::string last_header("");
483 
484  // Make a new log to sort entries alphabetically
485  std::map<std::pair<std::string, std::string>, PerfData> string_log;
486 
487  for (auto char_data : log)
488  if (summarize_logs)
489  {
490  string_log[std::make_pair(std::string(), char_data.first.first)] +=
491  char_data.second;
492  }
493  else
494  {
495  string_log[std::make_pair(char_data.first.first,
496  char_data.first.second)] =
497  char_data.second;
498  }
499 
500  for (auto pos : string_log)
501  {
502  const PerfData & perf_data = pos.second;
503 
504  // Only print the event if the count is non-zero.
505  if (perf_data.count != 0)
506  {
507  const unsigned int perf_count = perf_data.count;
508  const double perf_time = perf_data.tot_time;
509  const double perf_avg_time = perf_time / static_cast<double>(perf_count);
510  const double perf_time_incl_sub = perf_data.tot_time_incl_sub;
511  const double perf_avg_time_incl_sub = perf_time_incl_sub / static_cast<double>(perf_count);
512  const double perf_percent = (total_time != 0.) ? perf_time / total_time * 100. : 0.;
513  const double perf_percent_incl_sub = (total_time != 0.) ? perf_time_incl_sub / total_time * 100. : 0.;
514 
515  summed_function_calls += perf_count;
516  summed_total_time += perf_time;
517  summed_percentage += perf_percent;
518 
519  // Print the event name
520  if (pos.first.first == "")
521  oss << "| "
522  << std::setw(event_col_width)
523  << std::left
524  << pos.first.second;
525 
526  else
527  {
528  if (last_header != pos.first.first)
529  {
530  last_header = pos.first.first;
531 
532  // print blank line followed by header name
533  // (account for additional space before the
534  // header)
535  oss << "|"
536  << std::string(total_col_width, ' ')
537  << "|\n| "
538  << std::setw(total_col_width-1)
539  << std::left
540  << pos.first.first
541  << "|\n";
542  }
543 
544  oss << "| "
545  << std::setw(event_col_width-2)
546  << std::left
547  << pos.first.second;
548  }
549 
550 
551  // Print the number of calls to the event.
552  oss << std::setw(ncalls_col_width)
553  << perf_count;
554 
555  // Save the original stream flags
556  std::ios_base::fmtflags out_flags = oss.flags();
557 
558  // Print the total time spent in the event
559  oss << std::fixed
560  << std::setprecision(4)
561  << std::setw(tot_time_col_width)
562  << std::left
563  << perf_time;
564 
565 
566  // Print the average time per function call
567  oss << std::fixed
568  << std::setprecision(6)
569  << std::setw(avg_time_col_width)
570  << std::left
571  << perf_avg_time;
572 
573  // Print the total time spent in the event incl. sub-events
574  oss << std::fixed
575  << std::setprecision(4)
576  << std::setw(tot_time_incl_sub_col_width)
577  << std::left
578  << perf_time_incl_sub;
579 
580  // Print the average time per function call incl. sub-events
581  oss << std::fixed
582  << std::setprecision(6)
583  << std::setw(avg_time_incl_sub_col_width)
584  << std::left
585  << perf_avg_time_incl_sub;
586 
587  // Print the percentage of the time spent in the event
588  oss << std::fixed
589  << std::setprecision(2)
590  << std::setw(pct_active_col_width)
591  << std::left
592  << perf_percent;
593 
594  // Print the percentage of the time spent in the event incl. sub-events
595  oss << std::fixed
596  << std::setprecision(2)
597  << std::setw(pct_active_incl_sub_col_width)
598  << std::left
599  << perf_percent_incl_sub;
600 
601  // Reset the stream flags
602  oss.flags(out_flags);
603 
604  oss << "|\n";
605  }
606  }
607 
608  oss << ' '
609  << std::string(total_col_width, '-')
610  << "\n| "
611  << std::setw(event_col_width)
612  << std::left
613  << "Totals:";
614 
615  // Print the total number of logged function calls
616  // For routines which are called many times, summed_function_calls may
617  // exceed 7 digits. If this happens use, scientific notation.
618  if (summed_function_calls < 9999999)
619  oss << std::setw(ncalls_col_width)
620  << summed_function_calls;
621 
622  else
623  {
624  // Save the original stream flags
625  std::ios_base::fmtflags out_flags = oss.flags();
626 
627  oss << std::scientific
628  << std::setprecision(3)
629  << std::setw(ncalls_col_width)
630  << std::left
631  << static_cast<Real>(summed_function_calls);
632 
633  // Reset the stream flags
634  oss.flags(out_flags);
635  }
636 
637  // Print the total time spent in logged function calls. Don't bother saving/restoring
638  // the flags here since we are almost done with this stream anyway...
639  oss << std::fixed
640  << std::setprecision(4)
641  << std::setw(tot_time_col_width)
642  << std::left
643  << summed_total_time;
644 
645  // Null, the average time doesn't make sense as a total
646  oss << std::setw(avg_time_col_width) << "";
647 
648  // Same for times that include sub-events
649  oss << std::setw(tot_time_incl_sub_col_width)
650  << ""
651  << std::setw(avg_time_incl_sub_col_width)
652  << "";
653 
654  // Print the total percentage followed by dashed line
655  oss << std::fixed
656  << std::setprecision(2)
657  << std::setw(pct_active_col_width)
658  << std::left
659  << summed_percentage
660  << std::setw(pct_active_incl_sub_col_width)
661  << ""
662  << "|\n "
663  << std::string(total_col_width, '-')
664  << '\n';
665 
666  return oss.str();
667 }
668 
669 
670 
671 std::string PerfLog::get_log() const
672 {
673  std::ostringstream oss;
674 
675  if (log_events)
676  {
677  // Only print the log
678  // if it isn't empty
679  if (!log.empty())
680  {
681  // Possibly print machine info,
682  // but only do this once
683  if (!called)
684  {
685  called = true;
686  oss << get_info_header();
687  }
688  oss << get_perf_info();
689  }
690  }
691 
692  return oss.str();
693 }
694 
695 
696 
697 void PerfLog::print_log() const
698 {
699  if (log_events)
700  {
701  // Check to see if the log_string is empty, and if so,
702  // avoid printing an unnecessary newline.
703  std::string log_string = this->get_log();
704  if (log_string.size() > 0)
705  libMesh::out << log_string << std::endl;
706  }
707 }
708 
709 PerfData PerfLog::get_perf_data(const std::string & label, const std::string & header)
710 {
711  if (non_temporary_strings.count(label) &&
712  non_temporary_strings.count(header))
713  {
714  const char * label_c_str = non_temporary_strings[label].get();
715  const char * header_c_str = non_temporary_strings[header].get();
716  return log[std::make_pair(header_c_str, label_c_str)];
717  }
718 
719  auto iter = std::find_if
720  (log.begin(), log.end(),
721  [&label, &header] (log_type::const_reference a)
722  {
723  return
724  !std::strcmp(header.c_str(), a.first.first) &&
725  !std::strcmp(label.c_str(), a.first.second);
726  });
727 
728  libmesh_assert(iter != log.end());
729 
730  return iter->second;
731 }
732 
733 void PerfLog::start_event(const std::string & label,
734  const std::string & header)
735 {
736  this->push(label,header);
737 }
738 
739 
740 
741 void PerfLog::stop_event(const std::string & label,
742  const std::string & header)
743 {
744  this->pop(label,header);
745 }
746 
747 
748 
749 void PerfLog::pause_event(const std::string &,
750  const std::string &)
751 {
752  // nothing to do. pushing the next object on the stack will handle it
753 }
754 
755 
756 
757 void PerfLog::restart_event(const std::string &,
758  const std::string &)
759 {
760  // nothing to do. popping the top off the stack will handle it.
761 }
762 
763 
764 
765 void PerfLog::split_on_whitespace(const std::string & input, std::vector<std::string> & output) const
766 {
767  // Check for easy return
768  if (input.size()==0)
769  return;
770 
771  // Here we hard-code the string to split on, since the algorithm below
772  // is somewhat specific to it...
773  const std::string split_on("' '");
774 
775  size_t current_pos = 0;
776  while (true)
777  {
778  // Find next end location
779  if (size_t end_pos = input.find(split_on, current_pos);
780  end_pos != std::string::npos)
781  {
782  // Create substring. Note: the second argument to substr is
783  // the *length* of string to create, not the ending position!
784  output.push_back( input.substr(current_pos, end_pos - current_pos + 1) );
785 
786  // Update search starting position, make sure to go past the end of the split_on string, but
787  // include the previous single quote (hence the -1).
788  current_pos = end_pos + split_on.size() - 1;
789  }
790  else
791  {
792  // Push back whatever remains of the string onto the output.
793  // Note that substr with only 1 argument pushes back
794  // whatever remains of the string. This also handles the
795  // case where the string does not contain any matches.
796  output.push_back( input.substr(current_pos) );
797 
798  // We are done searching the string, so break out of the while loop
799  break;
800  }
801  }
802 }
803 
804 } // namespace libMesh
double tot_time_incl_sub
Total time spent in this event, including sub-events.
Definition: perf_log.h:79
void pop(const char *label, const char *header="")
Pop the event label off the stack, resuming any lower event.
Definition: perf_log.C:168
PerfLog(std::string label_name="", const bool log_events=true)
Constructor.
Definition: perf_log.C:55
processor_id_type global_n_processors()
Definition: libmesh_base.h:75
void fast_push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
Definition: perf_log.h:494
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
Definition: int_range.h:53
std::string get_timestamp()
Definition: timestamp.C:37
The PerfData class simply contains the performance data that is recorded for individual events...
Definition: perf_log.h:53
bool log_events
Flag to optionally disable all logging.
Definition: perf_log.h:346
int gettimeofday(struct timeval *tp, struct timezone *tzp)
double total_time
The total running time for recorded events.
Definition: perf_log.h:356
void stop_event(const std::string &label, const std::string &header="")
Stop monitoring the event named label.
Definition: perf_log.C:741
log_type log
The actual log.
Definition: perf_log.h:370
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.
Definition: perf_log.h:514
std::stack< PerfData * > log_stack
A stack to hold the current performance log trace.
Definition: perf_log.h:375
bool summarize_logs
Flag to optionally summarize logs.
Definition: perf_log.h:351
PerfData get_perf_data(const std::string &label, const std::string &header="")
Return the PerfData object associated with a label and header.
Definition: perf_log.C:709
std::string get_perf_info() const
Definition: perf_log.C:343
const std::string label_name
The label for this object.
Definition: perf_log.h:341
libmesh_assert(ctx)
std::string get_log() const
Definition: perf_log.C:671
std::string get_info_header() const
Definition: perf_log.C:176
void push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
Definition: perf_log.C:138
void restart_event(const std::string &label, const std::string &header="")
Restart monitoring the event.
Definition: perf_log.C:757
~PerfLog()
Destructor.
Definition: perf_log.C:70
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.
Definition: perf_log.C:765
void clear()
Clears all the internal data and restores the data structures to a pristine state.
Definition: perf_log.C:78
double tot_time
Total time spent in this event.
Definition: perf_log.h:74
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
OStreamProxy out
processor_id_type global_processor_id()
Definition: libmesh_base.h:85
void print_log() const
Print the log.
Definition: perf_log.C:697
void pause_event(const std::string &label, const std::string &header="")
Suspend monitoring of the event.
Definition: perf_log.C:749
unsigned int count
The number of times this event has been executed.
Definition: perf_log.h:97
struct timeval tstart
The time we were constructed or last cleared.
Definition: perf_log.h:361
static bool called
Flag indicating if print_log() has been called.
Definition: perf_log.h:382
std::map< std::string, std::unique_ptr< const char[]> > non_temporary_strings
Workaround to give us fixed pointers to character arrays for every string.
Definition: perf_log.h:399
void start_event(const std::string &label, const std::string &header="")
Start monitoring the event named label.
Definition: perf_log.C:733