1 // Copyright 2014-2017 the openage authors. See copying.md for legal info. 2 3 #include "externalprofiler.h" 4 5 #include <string> 6 7 #include "../config.h" 8 9 #if WITH_GPERFTOOLS_PROFILER 10 #include <gperftools/profiler.h> 11 #endif 12 13 #include "subprocess.h" 14 #include "os.h" 15 #include "../log/log.h" 16 17 18 namespace openage { 19 namespace util { 20 21 ExternalProfiler()22ExternalProfiler::ExternalProfiler() 23 : 24 currently_profiling{false}, 25 can_profile{WITH_GPERFTOOLS_PROFILER} {} 26 27 28 const char *const ExternalProfiler::profiling_filename = "/tmp/openage-gperftools-cpuprofile"; 29 const char *const ExternalProfiler::profiling_pdf_filename = "/tmp/openage-gperftools-cpuprofile.pdf"; 30 31 start()32void ExternalProfiler::start() { 33 if (not this->can_profile) { 34 log::log(MSG(err) << "Can not profile: gperftools is missing"); 35 return; 36 } 37 38 if (this->currently_profiling) { 39 log::log(MSG(info) << "Profiler is already running"); 40 return; 41 } 42 43 log::log(MSG(info) << "Starting profiler; writing data to " << this->profiling_filename); 44 45 this->currently_profiling = true; 46 #if WITH_GPERFTOOLS_PROFILER 47 ProfilerStart(this->profiling_filename); 48 #endif 49 } 50 51 stop()52void ExternalProfiler::stop() { 53 if (not this->can_profile) { 54 log::log(MSG(err) << "Can not profile: gperftools is missing"); 55 return; 56 } 57 58 if (not this->currently_profiling) { 59 log::log(MSG(err) << "Profiler is not currently running"); 60 return; 61 } 62 63 this->currently_profiling = false; 64 #if WITH_GPERFTOOLS_PROFILER 65 ProfilerStop(); 66 #endif 67 68 log::log(MSG(info) << "Profiler stopped; data written to " << this->profiling_filename); 69 } 70 71 show_results()72void ExternalProfiler::show_results() { 73 if (not this->can_profile) { 74 log::log(MSG(err) << "Can not profile: gperftools is missing"); 75 return; 76 } 77 78 if (this->currently_profiling) { 79 log::log(MSG(warn) << "Profiler is currently running; trying to show results anyway"); 80 } 81 82 #if WITH_GPERFTOOLS_PROFILER 83 std::string pprof_path = subprocess::which("google-pprof"); 84 85 // fallback to pprof 86 if (pprof_path.size() == 0) { 87 pprof_path = subprocess::which("pprof"); 88 } 89 90 if (pprof_path.size() == 0) { 91 log::log(ERR << "Can not process profiling results: google-pprof or pprof not found in PATH"); 92 return; 93 } 94 95 int retval = subprocess::call( 96 { 97 pprof_path.c_str(), 98 "--pdf", 99 "--", 100 os::self_exec_filename().c_str(), 101 this->profiling_filename, 102 nullptr 103 }, 104 true, 105 this->profiling_pdf_filename); 106 107 if (retval != 0) { 108 log::log(MSG(err) << "Profile analysis failed: " << retval); 109 return; 110 } 111 112 retval = os::execute_file(this->profiling_pdf_filename); 113 114 if (retval != 0) { 115 log::log(MSG(err) << 116 "Could not view profiling visualization " << 117 this->profiling_pdf_filename << ": " << retval); 118 return; 119 } 120 #endif 121 } 122 123 } // namespace util 124 } // namespace openage 125