Rework sampling trace counter names + new trace counters (#30)

* Rework sampling trace counter names + new trace counters

- reformulate trace counter names for easier comparison (thread sampling)
- new process-level trace counters for context switches (thread sampling)
- new process-level trace counters for page faults (thread sampling)
- new process-level trace counters for CPU time (thread sampling)
- new thread-level trace counters for context switches (sampling)
- new thread-level trace counters for page faults (sampling)

* tweak header include in backtrace.cpp

[ROCm/rocprofiler-systems commit: 1db3934f85]
This commit is contained in:
Jonathan R. Madsen
2022-06-09 13:43:07 -05:00
committed by GitHub
parent c6207d2336
commit 5c1e6ea127
4 changed files with 186 additions and 63 deletions
@@ -29,10 +29,14 @@
#include "library/timemory.hpp"
#include <timemory/components/rusage/backends.hpp>
#include <timemory/mpl/types.hpp>
#include <timemory/units.hpp>
#include <timemory/utility/procfs/cpuinfo.hpp>
#include <timemory/utility/type_list.hpp>
#include <cstdlib>
#include <string>
#include <sys/resource.h>
#include <tuple>
#include <utility>
#include <vector>
@@ -43,6 +47,9 @@ namespace omnitrace
{
namespace cpu_freq
{
template <typename... Tp>
using type_list = tim::type_list<Tp...>;
namespace
{
struct cpu_freq
@@ -51,19 +58,34 @@ struct cpu_page
{};
struct cpu_virt
{};
using cpu_data_tuple_t = std::tuple<size_t, int64_t, int64_t, std::vector<double>>;
struct cpu_context_switch
{};
struct cpu_page_fault
{};
struct cpu_user_mode_time
{};
struct cpu_kernel_mode_time
{};
using cpu_data_tuple_t = std::tuple<size_t, int64_t, int64_t, int64_t, int64_t, int64_t,
int64_t, std::vector<double>>;
std::set<size_t> enabled_cpu_freqs = {};
std::deque<cpu_data_tuple_t> cpu_data = {};
int64_t ncpu = threading::affinity::hw_concurrency();
template <typename... Types>
void init_perfetto_counter_tracks(type_list<Types...>)
{
(perfetto_counter_track<Types>::init(), ...);
}
} // namespace
void
setup()
{
perfetto_counter_track<cpu_freq>::init();
perfetto_counter_track<cpu_page>::init();
perfetto_counter_track<cpu_virt>::init();
init_perfetto_counter_tracks(
type_list<cpu_freq, cpu_page, cpu_virt, cpu_context_switch, cpu_page_fault,
cpu_user_mode_time, cpu_kernel_mode_time>{});
}
void
@@ -166,14 +188,51 @@ sample()
auto _ts = tim::get_clock_real_now<size_t, std::nano>();
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(),
std::move(_freqs));
_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
shutdown()
{}
namespace
{
template <typename... Types, size_t N = sizeof...(Types)>
void
config_perfetto_counter_tracks(type_list<Types...>, std::array<const char*, N> _labels,
std::array<const char*, N> _units)
{
auto _config = [&](auto _t) {
using type = std::decay_t<decltype(_t)>;
using track = perfetto_counter_track<type>;
constexpr auto _idx = tim::index_of<type, type_list<Types...>>::value;
if(!track::exists(0))
{
auto addendum = [&](const char* _v) { return JOIN(" ", "CPU", _v, "(S)"); };
track::emplace(0, addendum(_labels.at(_idx)), _units.at(_idx));
}
};
(_config(Types{}), ...);
}
template <typename Tp, typename... Args>
void
write_perfetto_counter_track(Args... _args)
{
using track = perfetto_counter_track<Tp>;
TRACE_COUNTER("sampling", track::at(0, 0), _args...);
}
} // namespace
void
post_process()
{
@@ -183,48 +242,56 @@ post_process()
using freq_track = perfetto_counter_track<cpu_freq>;
if(!freq_track::exists(_idx))
{
auto _devname = TIMEMORY_JOIN("", "[CPU ", _idx, "] ");
auto addendum = [&](const char* _v) { return _devname + std::string{ _v }; };
freq_track::emplace(_idx, addendum("Frequency (S)"), "MHz");
auto addendum = [&](const char* _v) {
return JOIN(" ", "CPU", _v, JOIN("", '[', _idx, ']'), "(S)");
};
freq_track::emplace(_idx, addendum("Frequency"), "MHz");
}
for(auto& itr : cpu_data)
{
uint64_t _ts = std::get<0>(itr);
double _freq = std::get<3>(itr).at(_offset);
double _freq = std::get<7>(itr).at(_offset);
TRACE_COUNTER("sampling", freq_track::at(_idx, 0), _ts, _freq);
}
};
auto _process_cpu_mem_usage = []() {
using page_track = perfetto_counter_track<cpu_page>;
using virt_track = perfetto_counter_track<cpu_virt>;
if(!page_track::exists(0))
{
auto _devname = TIMEMORY_JOIN("", "[CPU] ");
auto addendum = [&](const char* _v) { return _devname + std::string{ _v }; };
page_track::emplace(0, addendum("Memory Usage (S)"), "MB");
}
if(!virt_track::exists(0))
{
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");
}
auto _process_cpu_rusage = []() {
config_perfetto_counter_tracks(
type_list<cpu_page, cpu_virt, cpu_context_switch, cpu_page_fault,
cpu_user_mode_time, cpu_kernel_mode_time>{},
{ "Memory Usage", "Virtual Memory Usage", "Context Switches", "Page Faults",
"User CPU Time", "Kernel CPU Time" },
{ "MB", "MB", "", "", "sec", "sec" });
cpu_data_tuple_t* _last = nullptr;
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);
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);
if(_last)
{
_cntx -= std::get<3>(*_last);
_flts -= std::get<4>(*_last);
_user -= std::get<5>(*_last);
_kern -= std::get<6>(*_last);
}
write_perfetto_counter_track<cpu_page>(_ts, _page / units::megabyte);
write_perfetto_counter_track<cpu_virt>(_ts, _virt / units::megabyte);
write_perfetto_counter_track<cpu_context_switch>(_ts, _cntx);
write_perfetto_counter_track<cpu_page_fault>(_ts, _flts);
write_perfetto_counter_track<cpu_user_mode_time>(_ts, _user / units::sec);
write_perfetto_counter_track<cpu_kernel_mode_time>(_ts, _kern / units::sec);
_last = &itr;
}
};
_process_cpu_mem_usage();
_process_cpu_rusage();
for(auto itr = enabled_cpu_freqs.begin(); itr != enabled_cpu_freqs.end(); ++itr)
{
auto _idx = *itr;