diff --git a/projects/rocprofiler-systems/external/timemory b/projects/rocprofiler-systems/external/timemory index 83f911bc46..08313b1bf0 160000 --- a/projects/rocprofiler-systems/external/timemory +++ b/projects/rocprofiler-systems/external/timemory @@ -1 +1 @@ -Subproject commit 83f911bc464ab9d271d75391a977b28d6a8af874 +Subproject commit 08313b1bf0766dae6adc4c5015c28f17dd898464 diff --git a/projects/rocprofiler-systems/source/lib/omnitrace/library.cpp b/projects/rocprofiler-systems/source/lib/omnitrace/library.cpp index d5b9296c15..f87666dd20 100644 --- a/projects/rocprofiler-systems/source/lib/omnitrace/library.cpp +++ b/projects/rocprofiler-systems/source/lib/omnitrace/library.cpp @@ -41,6 +41,8 @@ #include "library/thread_sampler.hpp" #include "library/timemory.hpp" +#include + #include #include #include @@ -1291,6 +1293,18 @@ omnitrace_finalize_hidden(void) coverage::post_process(); } + tim::manager::instance()->add_metadata([](auto& ar) { + auto _maps = tim::procfs::read_maps(process::get_id()); + auto _libs = std::set{}; + for(auto& itr : _maps) + { + auto&& _path = itr.pathname; + if(!_path.empty() && _path.at(0) != '[') _libs.emplace(_path); + } + ar(tim::cereal::make_nvp("memory_maps_files", _libs), + tim::cereal::make_nvp("memory_maps", _maps)); + }); + OMNITRACE_VERBOSE_F(1, "Finalizing timemory...\n"); tim::timemory_finalize(); diff --git a/projects/rocprofiler-systems/source/lib/omnitrace/library/cpu_freq.cpp b/projects/rocprofiler-systems/source/lib/omnitrace/library/cpu_freq.cpp index 996f677d82..dcd6c7ce1f 100644 --- a/projects/rocprofiler-systems/source/lib/omnitrace/library/cpu_freq.cpp +++ b/projects/rocprofiler-systems/source/lib/omnitrace/library/cpu_freq.cpp @@ -28,11 +28,17 @@ #include "library/perfetto.hpp" #include "library/timemory.hpp" +#include +#include + #include #include +#include #include #include +namespace cpuinfo = tim::procfs::cpuinfo; + namespace omnitrace { namespace cpu_freq @@ -41,72 +47,30 @@ namespace { struct cpu_freq {}; -using freq_pair_t = std::pair; -std::vector> cpu_frequencies = {}; -std::set enabled_cpu_frequencies = {}; - -struct cpu_mem +struct cpu_page {}; -using cpu_mem_usage_pair_t = std::pair; -std::deque cpu_mem_usage = {}; - -int64_t ncpu = threading::affinity::hw_concurrency(); -std::unique_ptr ifs = {}; -std::vector cpu_mhz_pos = {}; +struct cpu_virt +{}; +using cpu_data_tuple_t = std::tuple>; +std::set enabled_cpu_freqs = {}; +std::deque cpu_data = {}; +int64_t ncpu = threading::affinity::hw_concurrency(); } // namespace void setup() { perfetto_counter_track::init(); - perfetto_counter_track::init(); + perfetto_counter_track::init(); + perfetto_counter_track::init(); } void config() { - auto _ncpu = threading::affinity::hw_concurrency(); - std::vector _cpu_mhz_pos{}; - std::ifstream _ifs{ "/proc/cpuinfo" }; - if(_ifs) - { - for(size_t i = 0; i < _ncpu; ++i) - { - short _n = 0; - std::string _st{}; - while(_ifs && _ifs.good()) - { - std::string _s{}; - _ifs >> _s; - if(!_ifs.good() || !_ifs) break; - - if(_s == "cpu" || _s == "MHz" || _s == ":") - { - ++_n; - _st += _s + " "; - } - else - { - _n = 0; - _st = {}; - } - - if(_n == 3) - { - size_t _pos = _ifs.tellg(); - _cpu_mhz_pos.emplace_back(_pos + 1); - _ifs >> _s; - if(!_ifs.good() || !_ifs) break; - OMNITRACE_BASIC_VERBOSE(3, "[%zu] %s %s (pos = %zu)\n", i, - _st.c_str(), _s.c_str(), _pos + 1); - break; - } - } - } - } - - _ifs.close(); + auto _ncpu = cpuinfo::freq::size(); + auto _enabled_freqs = std::set{}; auto _enabled_val = get_sampling_cpus(); for(auto& itr : _enabled_val) @@ -121,7 +85,7 @@ config() if(_enabled.empty()) { for(size_t i = 0; i < _ncpu; ++i) - enabled_cpu_frequencies.emplace(i); + _enabled_freqs.emplace(i); } for(auto&& _v : _enabled) { @@ -142,49 +106,68 @@ config() "Invalid CPU range specification: %s. Required format N-M, e.g. 0-4", _v.c_str()); for(size_t i = std::stoull(_vv.at(0)); i < std::stoull(_vv.at(1)); ++i) - enabled_cpu_frequencies.insert(i); + _enabled_freqs.emplace(i); } else { - enabled_cpu_frequencies.insert(std::stoull(_v)); + _enabled_freqs.emplace(std::stoull(_v)); } } } else if(_enabled_val == "all") { for(size_t i = 0; i < _ncpu; ++i) - enabled_cpu_frequencies.emplace(i); + _enabled_freqs.emplace(i); } else if(_enabled_val == "none") { - enabled_cpu_frequencies.clear(); + _enabled_freqs.clear(); } - cpu_frequencies.resize(_ncpu); - cpu_mhz_pos = _cpu_mhz_pos; - if(!enabled_cpu_frequencies.empty()) - ifs = std::make_unique("/proc/cpuinfo", std::ifstream::binary); + + for(auto itr : _enabled_freqs) + { + if(itr < cpuinfo::freq::size()) + _enabled_freqs.emplace(itr); + else + { + OMNITRACE_VERBOSE( + 0, "[cpu_freq::config] Warning! Removing invalid cpu %zu...\n", itr); + OMNITRACE_CI_FAIL(true, "[cpu_freq::config] CPU frequencies are disabled " + ":: unable to open /proc/cpuinfo"); + } + } + + if(!cpuinfo::freq{}) + { + OMNITRACE_VERBOSE(0, "[cpu_freq::config] Warning! CPU frequencies are disabled " + ":: unable to open /proc/cpuinfo"); + _enabled_freqs.clear(); + } + + OMNITRACE_CI_FAIL(!cpuinfo::freq{}, "[cpu_freq::config] CPU frequencies are disabled " + ":: unable to open /proc/cpuinfo"); + + enabled_cpu_freqs = _enabled_freqs; } void sample() { - cpu_mem_usage.emplace_back(tim::get_clock_real_now(), - tim::get_page_rss()); - - if(!ifs) return; - - auto _read_cpu_freq = [](size_t _idx) { - double _freq = 0; - ifs->seekg(cpu_mhz_pos.at(_idx), ifs->beg); - (*ifs) >> _freq; - return _freq; - }; + std::vector _freqs{}; + if(!enabled_cpu_freqs.empty()) + { + _freqs.reserve(enabled_cpu_freqs.size()); + auto&& _freq = cpuinfo::freq{}; + for(const auto& itr : enabled_cpu_freqs) + { + _freqs.emplace_back(_freq(itr)); + } + } auto _ts = tim::get_clock_real_now(); - for(const auto& itr : enabled_cpu_frequencies) - { - cpu_frequencies.at(itr).emplace_back(_ts, _read_cpu_freq(itr)); - } + + cpu_data.emplace_back(_ts, tim::get_page_rss(), tim::get_virt_mem(), + std::move(_freqs)); } void @@ -194,46 +177,62 @@ shutdown() void post_process() { - OMNITRACE_PRINT("Post-processing %zu cpu freqs and %zu memory usage entries\n", - cpu_frequencies.size(), cpu_mem_usage.size()); - auto _process_frequencies = [](size_t _idx) { - using counter_track = perfetto_counter_track; - if(!counter_track::exists(_idx)) + OMNITRACE_PRINT("Post-processing %zu cpu frequency and memory usage entries...\n", + cpu_data.size()); + auto _process_frequencies = [](size_t _idx, size_t _offset) { + using freq_track = perfetto_counter_track; + if(!freq_track::exists(_idx)) { auto _devname = TIMEMORY_JOIN("", "[CPU ", _idx, "] "); auto addendum = [&](const char* _v) { return _devname + std::string{ _v }; }; - counter_track::emplace(_idx, addendum("Frequency (S)"), "MHz"); + freq_track::emplace(_idx, addendum("Frequency (S)"), "MHz"); } - for(auto& itr : cpu_frequencies.at(_idx)) + for(auto& itr : cpu_data) { - uint64_t _ts = itr.first; - double _freq = itr.second; - TRACE_COUNTER("sampling", counter_track::at(_idx, 0), _ts, _freq); + uint64_t _ts = std::get<0>(itr); + double _freq = std::get<3>(itr).at(_offset); + TRACE_COUNTER("sampling", freq_track::at(_idx, 0), _ts, _freq); } }; auto _process_cpu_mem_usage = []() { - using counter_track = perfetto_counter_track; - if(!counter_track::exists(0)) + using page_track = perfetto_counter_track; + using virt_track = perfetto_counter_track; + + if(!page_track::exists(0)) { auto _devname = TIMEMORY_JOIN("", "[CPU] "); auto addendum = [&](const char* _v) { return _devname + std::string{ _v }; }; - counter_track::emplace(0, addendum("Memory Usage (S)"), "MB"); + page_track::emplace(0, addendum("Memory Usage (S)"), "MB"); } - for(auto& itr : cpu_mem_usage) + if(!virt_track::exists(0)) { - uint64_t _ts = itr.first; - double _mem_usage = itr.second; - TRACE_COUNTER("sampling", counter_track::at(0, 0), _ts, - _mem_usage / units::megabyte); + auto _devname = TIMEMORY_JOIN("", "[CPU] "); + auto addendum = [&](const char* _v) { return _devname + std::string{ _v }; }; + virt_track::emplace(0, addendum("Virtual Memory Usage (S)"), "MB"); + } + + for(auto& itr : cpu_data) + { + uint64_t _ts = std::get<0>(itr); + double _page = std::get<1>(itr); + double _virt = std::get<2>(itr); + TRACE_COUNTER("sampling", page_track::at(0, 0), _ts, _page / units::megabyte); + TRACE_COUNTER("sampling", virt_track::at(0, 0), _ts, _virt / units::megabyte); } }; _process_cpu_mem_usage(); - for(size_t i = 0; i < cpu_frequencies.size(); ++i) - _process_frequencies(i); + for(auto itr = enabled_cpu_freqs.begin(); itr != enabled_cpu_freqs.end(); ++itr) + { + auto _idx = *itr; + auto _offset = std::distance(enabled_cpu_freqs.begin(), itr); + _process_frequencies(_idx, _offset); + } + + enabled_cpu_freqs.clear(); } } // namespace cpu_freq } // namespace omnitrace