libMesh
Loading...
Searching...
No Matches
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
45namespace libMesh
46{
47
48
49// ------------------------------------------------------------
50// PerfLog class member functions
51
52bool PerfLog::called = false;
53
54
55PerfLog::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
102void 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
147void 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
157void 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
185void PerfLog::pop (const char * label,
186 const char * header)
187{
188 this->pop(std::string(label), std::string(header));
189}
190
191
192
193std::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
360std::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
688std::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
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
726PerfData 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
750void PerfLog::start_event(const std::string & label,
751 const std::string & header)
752{
753 this->push(label,header);
754}
755
756
757
758void PerfLog::stop_event(const std::string & label,
759 const std::string & header)
760{
761 this->pop(label,header);
762}
763
764
765
766void 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
774void 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
782void 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
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
Definition int_range.h:54
The PerfData class simply contains the performance data that is recorded for individual events.
Definition perf_log.h:62
double tot_time_incl_sub
Total time spent in this event, including sub-events.
Definition perf_log.h:87
double tot_time
Total time spent in this event.
Definition perf_log.h:82
unsigned int count
The number of times this event has been executed.
Definition perf_log.h:105
void start_event(const std::string &label, const std::string &header="")
Start monitoring the event named label.
Definition perf_log.C:750
void print_log() const
Print the log.
Definition perf_log.C:714
double total_time
The total running time for recorded events.
Definition perf_log.h:364
void pop(const char *label, const char *header="")
Pop the event label off the stack, resuming any lower event.
Definition perf_log.C:185
void clear()
Clears all the internal data and restores the data structures to a pristine state.
Definition perf_log.C:78
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::string get_log() const
Definition perf_log.C:688
void restart_event(const std::string &label, const std::string &header="")
Restart monitoring the event.
Definition perf_log.C:774
std::string get_perf_info() const
Definition perf_log.C:360
log_type log
The actual log.
Definition perf_log.h:378
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 fast_push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
Definition perf_log.h:502
struct timeval tstart
The time we were constructed or last cleared.
Definition perf_log.h:369
~PerfLog()
Destructor.
Definition perf_log.C:70
bool summarize_logs
Flag to optionally summarize logs.
Definition perf_log.h:359
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 pause_event(const std::string &label, const std::string &header="")
Suspend monitoring of the event.
Definition perf_log.C:766
PerfLog(std::string label_name="", const bool log_events=true)
Constructor.
Definition perf_log.C:55
const std::string label_name
The label for this object.
Definition perf_log.h:349
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
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
std::string get_info_header() const
Definition perf_log.C:193
void stop_event(const std::string &label, const std::string &header="")
Stop monitoring the event named label.
Definition perf_log.C:758
static bool called
Flag indicating if print_log() has been called.
Definition perf_log.h:390
bool log_events
Flag to optionally disable all logging.
Definition perf_log.h:354
std::stack< PerfData * > log_stack
A stack to hold the current performance log trace.
Definition perf_log.h:383
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
std::string get_timestamp()
Definition timestamp.C:37
The libMesh namespace provides an interface to certain functionality in the library.
processor_id_type global_processor_id()
libmesh_assert(ctx)
OStreamProxy out
processor_id_type global_n_processors()
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
int gettimeofday(struct timeval *tp, struct timezone *tzp)