diff --git a/source/lib/omnitrace/library.cpp b/source/lib/omnitrace/library.cpp index ce0da4d1c7..fe94b6d8ff 100644 --- a/source/lib/omnitrace/library.cpp +++ b/source/lib/omnitrace/library.cpp @@ -542,6 +542,24 @@ omnitrace_init_tooling_hidden() buffer_config->set_size_kb(buffer_size); buffer_config->set_fill_policy(_policy); + std::set _available_categories = {}; + std::set _disabled_categories = {}; + for(auto itr : { OMNITRACE_PERFETTO_CATEGORIES }) + _available_categories.emplace(itr.name); + auto _enabled_categories = config::get_perfetto_categories(); + for(const auto& itr : _available_categories) + { + if(!_enabled_categories.empty() && _enabled_categories.count(itr) == 0) + _disabled_categories.emplace(itr); + } + + for(const auto& itr : _disabled_categories) + { + OMNITRACE_VERBOSE(1, "Disabling perfetto track event category: %s\n", + itr.c_str()); + track_event_cfg.add_disabled_categories(itr); + } + auto* ds_cfg = cfg.add_data_sources()->mutable_config(); ds_cfg->set_name("track_event"); // this MUST be track_event ds_cfg->set_track_event_config_raw(track_event_cfg.SerializeAsString()); diff --git a/source/lib/omnitrace/library/config.cpp b/source/lib/omnitrace/library/config.cpp index 6542fa04d3..f9e4b6c520 100644 --- a/source/lib/omnitrace/library/config.cpp +++ b/source/lib/omnitrace/library/config.cpp @@ -24,6 +24,7 @@ #include "library/debug.hpp" #include "library/defines.hpp" #include "library/gpu.hpp" +#include "library/perfetto.hpp" #include #include @@ -73,6 +74,16 @@ get_setting_name(std::string _v) return _v; } +template +Tp +get_available_perfetto_categories() +{ + auto _v = Tp{}; + for(auto itr : { OMNITRACE_PERFETTO_CATEGORIES }) + tim::utility::emplace(_v, itr.name); + return _v; +} + #define OMNITRACE_CONFIG_SETTING(TYPE, ENV_NAME, DESCRIPTION, INITIAL_VALUE, ...) \ [&]() { \ auto _ret = _config->insert( \ @@ -399,6 +410,11 @@ configure_settings(bool _init) "discard", "perfetto", "data") ->set_choices({ "fill", "discard" }); + OMNITRACE_CONFIG_SETTING(std::string, "OMNITRACE_PERFETTO_CATEGORIES", + "Categories to collect within perfetto", "", "perfetto", + "data") + ->set_choices(get_available_perfetto_categories>()); + OMNITRACE_CONFIG_EXT_SETTING(int64_t, "OMNITRACE_CRITICAL_TRACE_COUNT", "Number of critical trace to export (0 == all)", int64_t{ 0 }, "data", "critical_trace", @@ -1383,6 +1399,20 @@ get_perfetto_fill_policy() return static_cast&>(*_v->second).get(); } +std::set +get_perfetto_categories() +{ + static auto _v = get_config()->find("OMNITRACE_PERFETTO_CATEGORIES"); + static auto _avail = get_available_perfetto_categories>(); + auto _ret = std::set{}; + for(auto itr : tim::delimit( + static_cast&>(*_v->second).get(), " ,;:")) + { + if(_avail.count(itr) > 0) _ret.emplace(itr); + } + return _ret; +} + uint64_t get_critical_trace_update_freq() { diff --git a/source/lib/omnitrace/library/config.hpp b/source/lib/omnitrace/library/config.hpp index 4333e19277..9389533c6f 100644 --- a/source/lib/omnitrace/library/config.hpp +++ b/source/lib/omnitrace/library/config.hpp @@ -240,6 +240,9 @@ get_perfetto_combined_traces(); std::string get_perfetto_fill_policy(); +std::set +get_perfetto_categories(); + uint64_t get_critical_trace_update_freq(); diff --git a/source/lib/omnitrace/library/cpu_freq.cpp b/source/lib/omnitrace/library/cpu_freq.cpp index 79bd4d982a..2f577513a9 100644 --- a/source/lib/omnitrace/library/cpu_freq.cpp +++ b/source/lib/omnitrace/library/cpu_freq.cpp @@ -22,6 +22,7 @@ #include "library/cpu_freq.hpp" #include "library/common.hpp" +#include "library/components/fwd.hpp" #include "library/components/pthread_create_gotcha.hpp" #include "library/config.hpp" #include "library/debug.hpp" @@ -53,22 +54,24 @@ using type_list = tim::type_list; namespace { -struct cpu_freq +struct cpu_freq // cpu frequency {}; -struct cpu_page +struct cpu_page // amount of memory allocated in pages {}; -struct cpu_virt +struct cpu_virt // virtual memory usage +{}; +struct cpu_peak // memory high-water mark {}; struct cpu_context_switch {}; struct cpu_page_fault {}; -struct cpu_user_mode_time +struct cpu_user_mode_time // cpu time spent in userspace {}; -struct cpu_kernel_mode_time +struct cpu_kernel_mode_time // cpu time spent in kernelspace {}; using cpu_data_tuple_t = std::tuple>; + int64_t, int64_t, std::vector>; std::set enabled_cpu_freqs = {}; std::deque cpu_data = {}; @@ -86,6 +89,7 @@ void init_perfetto_counter_tracks(type_list) TIMEMORY_DEFINE_NAME_TRAIT("cpu_freq", omnitrace::cpu_freq::cpu_freq); TIMEMORY_DEFINE_NAME_TRAIT("process_page_fault", omnitrace::cpu_freq::cpu_page); TIMEMORY_DEFINE_NAME_TRAIT("process_virtual_memory", omnitrace::cpu_freq::cpu_virt); +TIMEMORY_DEFINE_NAME_TRAIT("process_memory_hwm", omnitrace::cpu_freq::cpu_peak); TIMEMORY_DEFINE_NAME_TRAIT("process_context_switch", omnitrace::cpu_freq::cpu_context_switch); TIMEMORY_DEFINE_NAME_TRAIT("process_page_fault", omnitrace::cpu_freq::cpu_page_fault); @@ -102,8 +106,8 @@ void setup() { init_perfetto_counter_tracks( - type_list{}); + type_list{}); } void @@ -208,13 +212,13 @@ sample() tim::rusage_cache _rcache{ RUSAGE_SELF }; // user and kernel mode times are in microseconds - cpu_data.emplace_back(_ts, tim::get_page_rss(), tim::get_virt_mem(), - _rcache.get_num_priority_context_switch() + - _rcache.get_num_voluntary_context_switch(), - _rcache.get_num_major_page_faults() + - _rcache.get_num_minor_page_faults(), - _rcache.get_user_mode_time() * 1000, - _rcache.get_kernel_mode_time() * 1000, std::move(_freqs)); + cpu_data.emplace_back( + _ts, tim::get_page_rss(), tim::get_virt_mem(), _rcache.get_peak_rss(), + _rcache.get_num_priority_context_switch() + + _rcache.get_num_voluntary_context_switch(), + _rcache.get_num_major_page_faults() + _rcache.get_num_minor_page_faults(), + _rcache.get_user_mode_time() * 1000, _rcache.get_kernel_mode_time() * 1000, + std::move(_freqs)); } void @@ -228,6 +232,9 @@ void config_perfetto_counter_tracks(type_list, std::array _labels, std::array _units) { + static_assert(sizeof...(Types) == N, + "Error! Number of types != number of labels/units"); + auto _config = [&](auto _t) { using type = std::decay_t; using track = perfetto_counter_track; @@ -269,7 +276,7 @@ post_process() for(auto& itr : cpu_data) { uint64_t _ts = std::get<0>(itr); - double _freq = std::get<7>(itr).at(_offset); + double _freq = std::get<8>(itr).at(_offset); if(!pthread_create_gotcha::is_valid_execution_time(0, _ts)) continue; TRACE_COUNTER("cpu_freq", freq_track::at(_idx, 0), _ts, _freq); } @@ -280,11 +287,11 @@ post_process() auto _process_cpu_rusage = []() { config_perfetto_counter_tracks( - type_list{}, - { "Memory Usage", "Virtual Memory Usage", "Context Switches", "Page Faults", - "User Time", "Kernel Time" }, - { "MB", "MB", "", "", "sec", "sec" }); + { "Memory Usage", "Virtual Memory Usage", "Peak Memory", "Context Switches", + "Page Faults", "User Time", "Kernel Time" }, + { "MB", "MB", "MB", "", "", "sec", "sec" }); for(auto& itr : cpu_data) { @@ -293,12 +300,14 @@ post_process() double _page = std::get<1>(itr); double _virt = std::get<2>(itr); - uint64_t _cntx = std::get<3>(itr); - uint64_t _flts = std::get<4>(itr); - double _user = std::get<5>(itr); - double _kern = std::get<6>(itr); + double _peak = std::get<3>(itr); + uint64_t _cntx = std::get<4>(itr); + uint64_t _flts = std::get<5>(itr); + double _user = std::get<6>(itr); + double _kern = std::get<7>(itr); write_perfetto_counter_track(_ts, _page / units::megabyte); write_perfetto_counter_track(_ts, _virt / units::megabyte); + write_perfetto_counter_track(_ts, _peak / units::megabyte); write_perfetto_counter_track(_ts, _cntx); write_perfetto_counter_track(_ts, _flts); write_perfetto_counter_track(_ts, _user / units::sec); @@ -306,12 +315,13 @@ post_process() } auto _end_ts = pthread_create_gotcha::get_execution_time(0)->second; - write_perfetto_counter_track(_end_ts, 0); - write_perfetto_counter_track(_end_ts, 0); + write_perfetto_counter_track(_end_ts, 0.0); + write_perfetto_counter_track(_end_ts, 0.0); + write_perfetto_counter_track(_end_ts, 0.0); write_perfetto_counter_track(_end_ts, 0); write_perfetto_counter_track(_end_ts, 0); - write_perfetto_counter_track(_end_ts, 0); - write_perfetto_counter_track(_end_ts, 0); + write_perfetto_counter_track(_end_ts, 0.0); + write_perfetto_counter_track(_end_ts, 0.0); }; _process_cpu_rusage(); diff --git a/source/lib/omnitrace/library/perfetto.hpp b/source/lib/omnitrace/library/perfetto.hpp index 30daf2391a..34db2c8f59 100644 --- a/source/lib/omnitrace/library/perfetto.hpp +++ b/source/lib/omnitrace/library/perfetto.hpp @@ -61,6 +61,9 @@ perfetto::Category("process_page_fault") \ .SetDescription( \ "Memory page faults in process (collected in background thread)"), \ + perfetto::Category("process_memory_hwm") \ + .SetDescription("Memory High-Water Mark i.e. peak memory usage (collected " \ + "in background thread)"), \ perfetto::Category("process_virtual_memory") \ .SetDescription("Virtual memory usage in process in MB (collected in " \ "background thread)"), \