libMesh
perf_log.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2026 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  // The global perflog stack may not be thread-safe, but if we're
106  // creating threads we should have disabled it already
107  libmesh_assert_equal_to(Threads::active_threads, 1);
108 #ifdef LIBMESH_HAVE_OPENMP
109  // Users might be doing their own non-libMesh threading. We can't
110  // catch every case of that but we can catch OpenMP.
111  libmesh_assert_equal_to(omp_get_num_threads(), 1);
112 #endif
113 
114  const char * label_c_str;
115  const char * header_c_str;
116 
117  if (const auto label_it = non_temporary_strings.find(label);
118  label_it != non_temporary_strings.end())
119  label_c_str = label_it->second.get();
120  else
121  {
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();
126  non_temporary_strings[label] = std::move(newcopy);
127  }
128 
129  if (const auto header_it = non_temporary_strings.find(header);
130  header_it != non_temporary_strings.end())
131  header_c_str = header_it->second.get();
132  else
133  {
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();
138  non_temporary_strings[header] = std::move(newcopy);
139  }
140 
141  if (this->log_events)
142  this->fast_push(label_c_str, header_c_str);
143 }
144 
145 
146 
147 void PerfLog::push (const char * label,
148  const char * header)
149 {
150  this->push(std::string(label), std::string(header));
151 }
152 
153 
154 
155 
156 
157 void PerfLog::pop (const std::string & label,
158  const std::string & header)
159 {
160  // The global perflog stack may not be thread-safe, but if we're
161  // creating threads we should have disabled it already
162  libmesh_assert_equal_to(Threads::active_threads, 1);
163 #ifdef LIBMESH_HAVE_OPENMP
164  // Users might be doing their own non-libMesh threading. We can't
165  // catch every case of that but we can catch OpenMP.
166  libmesh_exceptionless_assert(omp_get_num_threads() == 1);
167 #endif
168 
169  const char * label_c_str = non_temporary_strings[label].get();
170  const char * header_c_str = non_temporary_strings[header].get();
171 
172  // This could happen if users are *mixing* string and char* APIs for
173  // the same label/header combination. For perfect backwards
174  // compatibility we should handle that, but there's just no fast way
175  // to do so.
176  libmesh_assert(label_c_str);
177  libmesh_assert(header_c_str);
178 
179  if (this->log_events)
180  this->fast_pop(label_c_str, header_c_str);
181 }
182 
183 
184 
185 void PerfLog::pop (const char * label,
186  const char * header)
187 {
188  this->pop(std::string(label), std::string(header));
189 }
190 
191 
192 
193 std::string PerfLog::get_info_header() const
194 {
195  std::ostringstream oss;
196 
197  if (log_events)
198  {
199  std::string date = Utility::get_timestamp();
200 
201 #ifdef LIBMESH_HAVE_SYS_UTSNAME_H
202  // Get system information
203  struct utsname sysInfo;
204  uname(&sysInfo);
205 #endif
206 
207  // Get user information
208  //
209  // Some systems, for example Crays, actually have getpwuid on the head-node
210  // but (if I understand correctly) a dynamically-linked glibc is not available
211  // on the backend, which is running a reduced operating system like Compute
212  // Node Linux. Thus functions like getpwuid cannot be called. This makes
213  // automatically testing for the existence of getpwuid on the login node
214  // difficult. The configure test would work on the login node but will fail
215  // on the backend. Hence we have added a configure flag, --disable-getpwuid,
216  // to manually turn this off.
217 #ifdef LIBMESH_HAVE_GETPWUID
218  struct passwd * p = getpwuid(getuid());
219 #endif
220  oss << "\n";
221 
222  // Construct string stream objects for each of the outputs
223  std::ostringstream
224  pid_stream,
225  nprocs_stream,
226  time_stream,
227  os_stream,
228  host_stream,
229  osrel_stream,
230  osver_stream,
231  machine_stream,
232  user_stream;
233 
234 
235  // Put pointers to these streams in a vector
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);
246 
247  // Fill string stream objects
249  {
250  pid_stream << "| Processor id: " << libMesh::global_processor_id();
251  nprocs_stream << "| Num Processors: " << libMesh::global_n_processors();
252  }
253 
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: ";
260 
261  time_stream << date;
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 ;
268 #else
269  os_stream << "Unknown";
270  host_stream << "Unknown";
271  osrel_stream << "Unknown";
272  osver_stream << "Unknown";
273  machine_stream << "Unknown";
274 
275 #endif
276  user_stream << "| Username: ";
277 #ifdef LIBMESH_HAVE_GETPWUID
278  if (p && p->pw_name)
279  user_stream << p->pw_name;
280  else
281 #endif
282  user_stream << "Unknown";
283 
284  // Parse the LIBMESH_CONFIGURE_INFO string literal before using it in PerfLog output
285  std::string libmesh_configure_info(LIBMESH_CONFIGURE_INFO);
286  std::vector<std::string> parsed_libmesh_configure_info;
287  this->split_on_whitespace(libmesh_configure_info,
288  parsed_libmesh_configure_info);
289 
290  // There should always be at at least one entry in
291  // parsed_libmesh_configure_info, even if the user just ran
292  // ../configure.
293  libmesh_assert_greater (parsed_libmesh_configure_info.size(), 0);
294 
295  // Find the longest string in all the streams
296  unsigned int max_length = 0;
297  for (auto & v_i : v)
298  if (v_i->str().size() > max_length)
299  max_length = cast_int<unsigned int>
300  (v_i->str().size());
301 
302  // Find the longest string in the parsed_libmesh_configure_info
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());
306 
307  // Print dashed line for the header
308  oss << ' '
309  << std::string(max_length+1, '-')
310  << '\n';
311 
312  // Loop over all the strings and add end formatting
313  for (auto & v_i : v)
314  {
315  if (v_i->str().size())
316  oss << v_i->str()
317  << std::setw (cast_int<int>
318  (max_length + 4 - v_i->str().size()))
319  << std::right
320  << "|\n";
321  }
322 
323  // Print out configuration header plus first parsed string. The
324  // magic number 18 below accounts for the length of the word
325  // 'Configuration'.
326  oss << "| Configuration: "
327  << parsed_libmesh_configure_info[0]
328  << std::setw (cast_int<int>
329  (max_length + 4 -
330  parsed_libmesh_configure_info[0].size() - 18))
331  << std::right
332  << "|\n";
333 
334  // Loop over the parsed_libmesh_configure_info and add end formatting. The magic
335  // number 3 below accounts for the leading 'pipe' character and indentation
336  for (auto i : IntRange<std::size_t>(1, parsed_libmesh_configure_info.size()))
337  {
338  oss << "| "
339  << parsed_libmesh_configure_info[i]
340  << std::setw (cast_int<int>
341  (max_length + 4 -
342  parsed_libmesh_configure_info[i].size() - 3))
343  << std::right
344  << "|\n";
345  }
346 
347 
348  // Print dashed line
349  oss << ' '
350  << std::string(max_length+1, '-')
351  << '\n';
352  }
353 
354  return oss.str();
355 }
356 
357 
358 
359 
360 std::string PerfLog::get_perf_info() const
361 {
362  std::ostringstream oss;
363 
364  if (!log_events || log.empty())
365  return oss.str();
366 
367  // Stop timing for this event.
368  struct timeval tstop;
369 
370  gettimeofday (&tstop, nullptr);
371 
372  const double elapsed_time = (static_cast<double>(tstop.tv_sec - tstart.tv_sec) +
373  static_cast<double>(tstop.tv_usec - tstart.tv_usec)*1.e-6);
374 
375  // Figure out the formatting required based on the event names
376  // Unsigned ints for each of the column widths
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;
385 
386  // Reset the event column width based on the longest event name plus
387  // a possible 2-character indentation, plus a space.
388  for (auto pos : log)
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);
392 
393  // Set the total width of the column
394  const unsigned int total_col_width =
395  event_col_width +
396  ncalls_col_width +
397  tot_time_col_width +
398  avg_time_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;
403 
404  // Print dashed line
405  oss << ' '
406  << std::string(total_col_width, '-')
407  << '\n';
408 
409  {
410  // Construct temporary message string
411  std::ostringstream temp;
412  temp << "| " << label_name << " Performance: Alive time=" << elapsed_time
413  << ", Active time=" << total_time;
414 
415  // Get the size of the temporary string
416  const unsigned int temp_size = cast_int<unsigned int>
417  (temp.str().size());
418 
419  // Send the temporary message to the output
420  oss << temp.str();
421 
422  // If this string is longer than the previously computed total
423  // column width, skip the additional formatting... this shouldn't
424  // happen often, hopefully. Add two additional characters for a
425  // space and a "|" character at the end.
426  if (temp_size < total_col_width+2)
427  oss << std::setw(total_col_width - temp_size + 2)
428  << std::right
429  << "|";
430 
431  oss << '\n';
432  }
433 
434  // Print dashed line
435  oss << ' '
436  << std::string(total_col_width, '-')
437  << '\n';
438 
439 
440  // Write out the header for the events listing
441  oss << "| "
442  << std::setw(event_col_width)
443  << std::left
444  << "Event"
445  << std::setw(ncalls_col_width)
446  << std::left
447  << "nCalls"
448  << std::setw(tot_time_col_width)
449  << std::left
450  << "Total Time"
451  << std::setw(avg_time_col_width)
452  << std::left
453  << "Avg Time"
454  << std::setw(tot_time_incl_sub_col_width)
455  << std::left
456  << "Total Time"
457  << std::setw(avg_time_incl_sub_col_width)
458  << std::left
459  << "Avg Time"
460  << std::setw(pct_active_col_width+pct_active_incl_sub_col_width)
461  << std::left
462  << "% of Active Time"
463  << "|\n"
464  << "| "
465  << std::setw(event_col_width)
466  << std::left
467  << ""
468  << std::setw(ncalls_col_width)
469  << std::left
470  << ""
471  << std::setw(tot_time_col_width)
472  << std::left
473  << "w/o Sub"
474  << std::setw(avg_time_col_width)
475  << std::left
476  << "w/o Sub"
477  << std::setw(tot_time_incl_sub_col_width)
478  << std::left
479  << "With Sub"
480  << std::setw(avg_time_incl_sub_col_width)
481  << std::left
482  << "With Sub"
483  << std::setw(pct_active_col_width)
484  << std::left
485  << "w/o S"
486  << std::setw(pct_active_incl_sub_col_width)
487  << std::left
488  << "With S"
489  << "|\n|"
490  << std::string(total_col_width, '-')
491  << "|\n|"
492  << std::string(total_col_width, ' ')
493  << "|\n";
494 
495  unsigned int summed_function_calls = 0;
496  double summed_total_time = 0;
497  double summed_percentage = 0;
498 
499  std::string last_header("");
500 
501  // Make a new log to sort entries alphabetically
502  std::map<std::pair<std::string, std::string>, PerfData> string_log;
503 
504  for (auto char_data : log)
505  if (summarize_logs)
506  {
507  string_log[std::make_pair(std::string(), char_data.first.first)] +=
508  char_data.second;
509  }
510  else
511  {
512  string_log[std::make_pair(char_data.first.first,
513  char_data.first.second)] =
514  char_data.second;
515  }
516 
517  for (auto pos : string_log)
518  {
519  const PerfData & perf_data = pos.second;
520 
521  // Only print the event if the count is non-zero.
522  if (perf_data.count != 0)
523  {
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);
527  const double perf_time_incl_sub = perf_data.tot_time_incl_sub;
528  const double perf_avg_time_incl_sub = perf_time_incl_sub / static_cast<double>(perf_count);
529  const double perf_percent = (total_time != 0.) ? perf_time / total_time * 100. : 0.;
530  const double perf_percent_incl_sub = (total_time != 0.) ? perf_time_incl_sub / total_time * 100. : 0.;
531 
532  summed_function_calls += perf_count;
533  summed_total_time += perf_time;
534  summed_percentage += perf_percent;
535 
536  // Print the event name
537  if (pos.first.first == "")
538  oss << "| "
539  << std::setw(event_col_width)
540  << std::left
541  << pos.first.second;
542 
543  else
544  {
545  if (last_header != pos.first.first)
546  {
547  last_header = pos.first.first;
548 
549  // print blank line followed by header name
550  // (account for additional space before the
551  // header)
552  oss << "|"
553  << std::string(total_col_width, ' ')
554  << "|\n| "
555  << std::setw(total_col_width-1)
556  << std::left
557  << pos.first.first
558  << "|\n";
559  }
560 
561  oss << "| "
562  << std::setw(event_col_width-2)
563  << std::left
564  << pos.first.second;
565  }
566 
567 
568  // Print the number of calls to the event.
569  oss << std::setw(ncalls_col_width)
570  << perf_count;
571 
572  // Save the original stream flags
573  std::ios_base::fmtflags out_flags = oss.flags();
574 
575  // Print the total time spent in the event
576  oss << std::fixed
577  << std::setprecision(4)
578  << std::setw(tot_time_col_width)
579  << std::left
580  << perf_time;
581 
582 
583  // Print the average time per function call
584  oss << std::fixed
585  << std::setprecision(6)
586  << std::setw(avg_time_col_width)
587  << std::left
588  << perf_avg_time;
589 
590  // Print the total time spent in the event incl. sub-events
591  oss << std::fixed
592  << std::setprecision(4)
593  << std::setw(tot_time_incl_sub_col_width)
594  << std::left
595  << perf_time_incl_sub;
596 
597  // Print the average time per function call incl. sub-events
598  oss << std::fixed
599  << std::setprecision(6)
600  << std::setw(avg_time_incl_sub_col_width)
601  << std::left
602  << perf_avg_time_incl_sub;
603 
604  // Print the percentage of the time spent in the event
605  oss << std::fixed
606  << std::setprecision(2)
607  << std::setw(pct_active_col_width)
608  << std::left
609  << perf_percent;
610 
611  // Print the percentage of the time spent in the event incl. sub-events
612  oss << std::fixed
613  << std::setprecision(2)
614  << std::setw(pct_active_incl_sub_col_width)
615  << std::left
616  << perf_percent_incl_sub;
617 
618  // Reset the stream flags
619  oss.flags(out_flags);
620 
621  oss << "|\n";
622  }
623  }
624 
625  oss << ' '
626  << std::string(total_col_width, '-')
627  << "\n| "
628  << std::setw(event_col_width)
629  << std::left
630  << "Totals:";
631 
632  // Print the total number of logged function calls
633  // For routines which are called many times, summed_function_calls may
634  // exceed 7 digits. If this happens use, scientific notation.
635  if (summed_function_calls < 9999999)
636  oss << std::setw(ncalls_col_width)
637  << summed_function_calls;
638 
639  else
640  {
641  // Save the original stream flags
642  std::ios_base::fmtflags out_flags = oss.flags();
643 
644  oss << std::scientific
645  << std::setprecision(3)
646  << std::setw(ncalls_col_width)
647  << std::left
648  << static_cast<Real>(summed_function_calls);
649 
650  // Reset the stream flags
651  oss.flags(out_flags);
652  }
653 
654  // Print the total time spent in logged function calls. Don't bother saving/restoring
655  // the flags here since we are almost done with this stream anyway...
656  oss << std::fixed
657  << std::setprecision(4)
658  << std::setw(tot_time_col_width)
659  << std::left
660  << summed_total_time;
661 
662  // Null, the average time doesn't make sense as a total
663  oss << std::setw(avg_time_col_width) << "";
664 
665  // Same for times that include sub-events
666  oss << std::setw(tot_time_incl_sub_col_width)
667  << ""
668  << std::setw(avg_time_incl_sub_col_width)
669  << "";
670 
671  // Print the total percentage followed by dashed line
672  oss << std::fixed
673  << std::setprecision(2)
674  << std::setw(pct_active_col_width)
675  << std::left
676  << summed_percentage
677  << std::setw(pct_active_incl_sub_col_width)
678  << ""
679  << "|\n "
680  << std::string(total_col_width, '-')
681  << '\n';
682 
683  return oss.str();
684 }
685 
686 
687 
688 std::string PerfLog::get_log() const
689 {
690  std::ostringstream oss;
691 
692  if (log_events)
693  {
694  // Only print the log
695  // if it isn't empty
696  if (!log.empty())
697  {
698  // Possibly print machine info,
699  // but only do this once
700  if (!called)
701  {
702  called = true;
703  oss << get_info_header();
704  }
705  oss << get_perf_info();
706  }
707  }
708 
709  return oss.str();
710 }
711 
712 
713 
714 void PerfLog::print_log() const
715 {
716  if (log_events)
717  {
718  // Check to see if the log_string is empty, and if so,
719  // avoid printing an unnecessary newline.
720  std::string log_string = this->get_log();
721  if (log_string.size() > 0)
722  libMesh::out << log_string << std::endl;
723  }
724 }
725 
726 PerfData PerfLog::get_perf_data(const std::string & label, const std::string & header)
727 {
728  if (non_temporary_strings.count(label) &&
729  non_temporary_strings.count(header))
730  {
731  const char * label_c_str = non_temporary_strings[label].get();
732  const char * header_c_str = non_temporary_strings[header].get();
733  return log[std::make_pair(header_c_str, label_c_str)];
734  }
735 
736  auto iter = std::find_if
737  (log.begin(), log.end(),
738  [&label, &header] (log_type::const_reference a)
739  {
740  return
741  !std::strcmp(header.c_str(), a.first.first) &&
742  !std::strcmp(label.c_str(), a.first.second);
743  });
744 
745  libmesh_assert(iter != log.end());
746 
747  return iter->second;
748 }
749 
750 void PerfLog::start_event(const std::string & label,
751  const std::string & header)
752 {
753  this->push(label,header);
754 }
755 
756 
757 
758 void PerfLog::stop_event(const std::string & label,
759  const std::string & header)
760 {
761  this->pop(label,header);
762 }
763 
764 
765 
766 void PerfLog::pause_event(const std::string &,
767  const std::string &)
768 {
769  // nothing to do. pushing the next object on the stack will handle it
770 }
771 
772 
773 
774 void PerfLog::restart_event(const std::string &,
775  const std::string &)
776 {
777  // nothing to do. popping the top off the stack will handle it.
778 }
779 
780 
781 
782 void PerfLog::split_on_whitespace(const std::string & input, std::vector<std::string> & output) const
783 {
784  // Check for easy return
785  if (input.size()==0)
786  return;
787 
788  // Here we hard-code the string to split on, since the algorithm below
789  // is somewhat specific to it...
790  const std::string split_on("' '");
791 
792  size_t current_pos = 0;
793  while (true)
794  {
795  // Find next end location
796  if (size_t end_pos = input.find(split_on, current_pos);
797  end_pos != std::string::npos)
798  {
799  // Create substring. Note: the second argument to substr is
800  // the *length* of string to create, not the ending position!
801  output.push_back( input.substr(current_pos, end_pos - current_pos + 1) );
802 
803  // Update search starting position, make sure to go past the end of the split_on string, but
804  // include the previous single quote (hence the -1).
805  current_pos = end_pos + split_on.size() - 1;
806  }
807  else
808  {
809  // Push back whatever remains of the string onto the output.
810  // Note that substr with only 1 argument pushes back
811  // whatever remains of the string. This also handles the
812  // case where the string does not contain any matches.
813  output.push_back( input.substr(current_pos) );
814 
815  // We are done searching the string, so break out of the while loop
816  break;
817  }
818  }
819 }
820 
821 } // namespace libMesh
double tot_time_incl_sub
Total time spent in this event, including sub-events.
Definition: perf_log.h:87
void pop(const char *label, const char *header="")
Pop the event label off the stack, resuming any lower event.
Definition: perf_log.C:185
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:88
void fast_push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
Definition: perf_log.h:502
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:61
bool log_events
Flag to optionally disable all logging.
Definition: perf_log.h:354
int gettimeofday(struct timeval *tp, struct timezone *tzp)
double total_time
The total running time for recorded events.
Definition: perf_log.h:364
void stop_event(const std::string &label, const std::string &header="")
Stop monitoring the event named label.
Definition: perf_log.C:758
log_type log
The actual log.
Definition: perf_log.h:378
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:539
std::stack< PerfData * > log_stack
A stack to hold the current performance log trace.
Definition: perf_log.h:383
bool summarize_logs
Flag to optionally summarize logs.
Definition: perf_log.h:359
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:726
std::string get_perf_info() const
Definition: perf_log.C:360
const std::string label_name
The label for this object.
Definition: perf_log.h:349
libmesh_assert(ctx)
std::string get_log() const
Definition: perf_log.C:688
std::string get_info_header() const
Definition: perf_log.C:193
void push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
Definition: perf_log.C:147
void restart_event(const std::string &label, const std::string &header="")
Restart monitoring the event.
Definition: perf_log.C:774
~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:782
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:82
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
OStreamProxy out
int active_threads
An integer which is set to the number of active threads when we are in a Threads:: parallel operation...
Definition: threads.C:32
processor_id_type global_processor_id()
Definition: libmesh_base.h:98
void print_log() const
Print the log.
Definition: perf_log.C:714
void pause_event(const std::string &label, const std::string &header="")
Suspend monitoring of the event.
Definition: perf_log.C:766
unsigned int count
The number of times this event has been executed.
Definition: perf_log.h:105
struct timeval tstart
The time we were constructed or last cleared.
Definition: perf_log.h:369
static bool called
Flag indicating if print_log() has been called.
Definition: perf_log.h:390
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:407
void start_event(const std::string &label, const std::string &header="")
Start monitoring the event named label.
Definition: perf_log.C:750