Optional perfetto annotations (#206)
* Misc tweaks - C API function print with warning colors - split region/trace start/stop functions into regions.cpp file * Config option for disabling perfetto annotations * Missing checks in roctracer.cpp and sampling.cpp * Verbose makefile in CI * run-ci uses -VV * Fix gcc-7 maybe-uninitialized warning * Fix push/pop perfetto - moving perfetto::EventContext was causing errors
This commit is contained in:
committed by
GitHub
vanhempi
2135f82ab8
commit
2f16e2ecb1
Vendored
+1
-1
Submodule external/timemory updated: a1538e4352...04a8679c09
@@ -247,7 +247,7 @@ if __name__ == "__main__":
|
||||
"-S",
|
||||
os.path.join(args.binary_dir, "dashboard.cmake"),
|
||||
"--output-on-failure",
|
||||
"-V",
|
||||
"-VV",
|
||||
]
|
||||
+ ctest_args,
|
||||
check=True,
|
||||
|
||||
@@ -56,8 +56,8 @@ add_library(omnitrace::omnitrace-object-library ALIAS omnitrace-object-library)
|
||||
|
||||
target_sources(
|
||||
omnitrace-object-library
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/library.cpp ${CMAKE_CURRENT_LIST_DIR}/api.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/api.hpp)
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/library.cpp ${CMAKE_CURRENT_LIST_DIR}/regions.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/api.cpp ${CMAKE_CURRENT_LIST_DIR}/api.hpp)
|
||||
|
||||
add_subdirectory(library)
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ omnitrace_push_region(const char* _name)
|
||||
omnitrace_push_region_hidden(_name);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(1, "Exception caught: %s\n", _e.what());
|
||||
OMNITRACE_WARNING_F(1, "Exception caught: %s\n", _e.what());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -60,7 +60,7 @@ omnitrace_pop_region(const char* _name)
|
||||
omnitrace_pop_region_hidden(_name);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(1, "Exception caught: %s\n", _e.what());
|
||||
OMNITRACE_WARNING_F(1, "Exception caught: %s\n", _e.what());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -77,7 +77,7 @@ omnitrace_push_category_region(omnitrace_category_t _category, const char* _name
|
||||
_annotation_count);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(1, "Exception caught: %s\n", _e.what());
|
||||
OMNITRACE_WARNING_F(1, "Exception caught: %s\n", _e.what());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -94,7 +94,7 @@ omnitrace_pop_category_region(omnitrace_category_t _category, const char* _name,
|
||||
_annotation_count);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(1, "Exception caught: %s\n", _e.what());
|
||||
OMNITRACE_WARNING_F(1, "Exception caught: %s\n", _e.what());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
#include "api.hpp"
|
||||
#include "common/setup.hpp"
|
||||
#include "library/components/category_region.hpp"
|
||||
#include "library/components/exit_gotcha.hpp"
|
||||
#include "library/components/fork_gotcha.hpp"
|
||||
#include "library/components/fwd.hpp"
|
||||
@@ -152,132 +151,6 @@ using Device = critical_trace::Device;
|
||||
using Phase = critical_trace::Phase;
|
||||
} // namespace
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_trace_hidden(const char* name)
|
||||
{
|
||||
component::category_region<category::host>::start(name);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_trace_hidden(const char* name)
|
||||
{
|
||||
component::category_region<category::host>::stop(name);
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
///
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_region_hidden(const char* name)
|
||||
{
|
||||
component::category_region<category::user>::start(name);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_region_hidden(const char* name)
|
||||
{
|
||||
component::category_region<category::user>::stop(name);
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
///
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <size_t Idx, size_t... Tail>
|
||||
void
|
||||
invoke_category_region_start(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count, std::index_sequence<Idx, Tail...>)
|
||||
{
|
||||
static_assert(Idx > OMNITRACE_CATEGORY_NONE && Idx < OMNITRACE_CATEGORY_LAST,
|
||||
"Error! index sequence should only contain values which are greater "
|
||||
"than OMNITRACE_CATEGORY_NONE and less than OMNITRACE_CATEGORY_LAST");
|
||||
|
||||
if(_category == Idx)
|
||||
{
|
||||
using category_type = category_type_id_t<Idx>;
|
||||
component::category_region<category_type>::start(
|
||||
name, [&](::perfetto::EventContext ctx) {
|
||||
if(_annotations)
|
||||
{
|
||||
for(size_t i = 0; i < _annotation_count; ++i)
|
||||
tracing::add_perfetto_annotation(ctx, _annotations[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr size_t remaining = sizeof...(Tail);
|
||||
if constexpr(remaining > 0)
|
||||
invoke_category_region_start(_category, name, _annotations, _annotation_count,
|
||||
std::index_sequence<Tail...>{});
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <size_t Idx, size_t... Tail>
|
||||
void
|
||||
invoke_category_region_stop(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count, std::index_sequence<Idx, Tail...>)
|
||||
{
|
||||
static_assert(Idx > OMNITRACE_CATEGORY_NONE && Idx < OMNITRACE_CATEGORY_LAST,
|
||||
"Error! index sequence should only contain values which are greater "
|
||||
"than OMNITRACE_CATEGORY_NONE and less than OMNITRACE_CATEGORY_LAST");
|
||||
|
||||
if(_category == Idx)
|
||||
{
|
||||
using category_type = category_type_id_t<Idx>;
|
||||
component::category_region<category_type>::stop(
|
||||
name, [&](::perfetto::EventContext ctx) {
|
||||
if(_annotations)
|
||||
{
|
||||
for(size_t i = 0; i < _annotation_count; ++i)
|
||||
tracing::add_perfetto_annotation(ctx, _annotations[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr size_t remaining = sizeof...(Tail);
|
||||
if constexpr(remaining > 0)
|
||||
invoke_category_region_stop(_category, name, _annotations, _annotation_count,
|
||||
std::index_sequence<Tail...>{});
|
||||
}
|
||||
}
|
||||
} // namespace omnitrace
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_category_region_hidden(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
invoke_category_region_start(
|
||||
_category, name, _annotations, _annotation_count,
|
||||
utility::make_index_sequence_range<1, OMNITRACE_CATEGORY_LAST>{});
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_category_region_hidden(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
invoke_category_region_stop(
|
||||
_category, name, _annotations, _annotation_count,
|
||||
utility::make_index_sequence_range<1, OMNITRACE_CATEGORY_LAST>{});
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
///
|
||||
|
||||
@@ -91,6 +91,9 @@ template <typename... OptsT, typename... Args>
|
||||
void
|
||||
category_region<CategoryT>::start(std::string_view name, Args&&... args)
|
||||
{
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
// unconditionally return if thread is disabled or finalized
|
||||
if(get_thread_state() == ThreadState::Disabled) return;
|
||||
if(get_state() == State::Finalized) return;
|
||||
@@ -167,6 +170,9 @@ template <typename... OptsT, typename... Args>
|
||||
void
|
||||
category_region<CategoryT>::stop(std::string_view name, Args&&... args)
|
||||
{
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
if(get_thread_state() == ThreadState::Disabled) return;
|
||||
|
||||
OMNITRACE_SCOPED_THREAD_STATE(ThreadState::Internal);
|
||||
@@ -249,10 +255,16 @@ void
|
||||
category_region<CategoryT>::audit(const gotcha_data_t& _data, audit::incoming,
|
||||
Args&&... _args)
|
||||
{
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
start<OptsT...>(_data.tool_id.c_str(), [&](perfetto::EventContext ctx) {
|
||||
int64_t _n = 0;
|
||||
OMNITRACE_FOLD_EXPRESSION(tracing::add_perfetto_annotation(
|
||||
ctx, tim::try_demangle<std::remove_reference_t<Args>>(), _args, _n++));
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
int64_t _n = 0;
|
||||
OMNITRACE_FOLD_EXPRESSION(tracing::add_perfetto_annotation(
|
||||
ctx, tim::try_demangle<std::remove_reference_t<Args>>(), _args, _n++));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -262,7 +274,13 @@ void
|
||||
category_region<CategoryT>::audit(const gotcha_data_t& _data, audit::outgoing,
|
||||
Args&&... _args)
|
||||
{
|
||||
stop<OptsT...>(_data.tool_id.c_str(), "return", JOIN(", ", _args...));
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
stop<OptsT...>(_data.tool_id.c_str(), [&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
tracing::add_perfetto_annotation(ctx, "return", JOIN(", ", _args...));
|
||||
});
|
||||
}
|
||||
|
||||
template <typename CategoryT>
|
||||
@@ -271,10 +289,16 @@ void
|
||||
category_region<CategoryT>::audit(std::string_view _name, audit::incoming,
|
||||
Args&&... _args)
|
||||
{
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
start<OptsT...>(_name.data(), [&](perfetto::EventContext ctx) {
|
||||
int64_t _n = 0;
|
||||
OMNITRACE_FOLD_EXPRESSION(tracing::add_perfetto_annotation(
|
||||
ctx, tim::try_demangle<std::remove_reference_t<Args>>(), _args, _n++));
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
int64_t _n = 0;
|
||||
OMNITRACE_FOLD_EXPRESSION(tracing::add_perfetto_annotation(
|
||||
ctx, tim::try_demangle<std::remove_reference_t<Args>>(), _args, _n++));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -284,7 +308,13 @@ void
|
||||
category_region<CategoryT>::audit(std::string_view _name, audit::outgoing,
|
||||
Args&&... _args)
|
||||
{
|
||||
stop<OptsT...>(_name.data(), "return", JOIN(", ", _args...));
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
stop<OptsT...>(_name.data(), [&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
tracing::add_perfetto_annotation(ctx, "return", JOIN(", ", _args...));
|
||||
});
|
||||
}
|
||||
|
||||
template <typename CategoryT>
|
||||
|
||||
@@ -419,7 +419,8 @@ pthread_create_gotcha::operator()(pthread_t* thread, const pthread_attr_t* attr,
|
||||
_promise->get_future().wait_for(std::chrono::milliseconds{ 500 });
|
||||
}
|
||||
|
||||
if(_use_bundle) stop_bundle(*_bundle, threading::get_id(), audit::outgoing{}, _ret);
|
||||
if(_use_bundle)
|
||||
stop_bundle(*_bundle, _info->index_data->sequent_value, audit::outgoing{}, _ret);
|
||||
|
||||
// unblock the signals in the entire process
|
||||
if(_enable_sampling && !_blocked.empty())
|
||||
|
||||
@@ -588,6 +588,13 @@ configure_settings(bool _init)
|
||||
"data", "advanced")
|
||||
->set_choices(get_available_perfetto_categories<std::vector<std::string>>());
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_PERFETTO_ANNOTATIONS",
|
||||
"Include debug annotations in perfetto trace. When enabled, "
|
||||
"this feature will encode information such as the values of "
|
||||
"the function arguments (when available). Disabling this "
|
||||
"feature may dramatically reduce the size of the trace",
|
||||
true, "perfetto", "data", "debugging", "advanced");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
uint64_t, "OMNITRACE_THREAD_POOL_SIZE",
|
||||
"Max number of threads for processing background tasks",
|
||||
@@ -1741,6 +1748,13 @@ get_perfetto_categories()
|
||||
return _ret;
|
||||
}
|
||||
|
||||
bool
|
||||
get_perfetto_annotations()
|
||||
{
|
||||
static auto _v = get_config()->find("OMNITRACE_PERFETTO_ANNOTATIONS");
|
||||
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
uint64_t
|
||||
get_critical_trace_update_freq()
|
||||
{
|
||||
|
||||
@@ -247,6 +247,9 @@ get_perfetto_fill_policy();
|
||||
std::set<std::string>
|
||||
get_perfetto_categories();
|
||||
|
||||
bool
|
||||
get_perfetto_annotations() OMNITRACE_HOT;
|
||||
|
||||
uint64_t
|
||||
get_critical_trace_update_freq();
|
||||
|
||||
|
||||
@@ -305,9 +305,21 @@ hsa_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
uint64_t _beg_ts = begin_timestamp;
|
||||
uint64_t _end_ts = end_timestamp;
|
||||
tracing::push_perfetto_ts(category::rocm_hsa{}, _name, _beg_ts,
|
||||
"begin_ns", _beg_ts);
|
||||
[&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(
|
||||
ctx, "begin_ns", _beg_ts);
|
||||
}
|
||||
});
|
||||
tracing::pop_perfetto_ts(category::rocm_hsa{}, _name, _end_ts,
|
||||
"end_ns", _end_ts);
|
||||
[&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(
|
||||
ctx, "end_ns", _end_ts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(get_use_timemory())
|
||||
@@ -378,8 +390,20 @@ hsa_activity_callback(uint32_t op, activity_record_t* record, void* arg)
|
||||
{
|
||||
uint64_t _beg = _beg_ns;
|
||||
uint64_t _end = _end_ns;
|
||||
tracing::push_perfetto_ts(category::device_hsa{}, *_name, _beg, "begin_ns", _beg);
|
||||
tracing::pop_perfetto_ts(category::device_hsa{}, *_name, _end, "end_ns", _end);
|
||||
tracing::push_perfetto_ts(
|
||||
category::device_hsa{}, *_name, _beg, [&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "begin_ns", _beg);
|
||||
}
|
||||
});
|
||||
tracing::pop_perfetto_ts(
|
||||
category::device_hsa{}, *_name, _end, [&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "end_ns", _end);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
auto _func = [_beg_ns, _end_ns, _name]() {
|
||||
@@ -701,9 +725,19 @@ hip_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
auto _api_id = static_cast<hip_api_id_t>(cid);
|
||||
tracing::push_perfetto_ts(
|
||||
category::rocm_hip{}, op_name, _ts, perfetto::Flow::ProcessScoped(_cid),
|
||||
"begin_ns", static_cast<uint64_t>(_ts), "pcid", _parent_cid, "cid", _cid,
|
||||
"device", _device_id, "tid", _tid, "depth", _depth, "corr_id", _corr_id,
|
||||
"args", hip_api_string(_api_id, data));
|
||||
[&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "begin_ns", _ts);
|
||||
tracing::add_perfetto_annotation(ctx, "pcid", _parent_cid);
|
||||
tracing::add_perfetto_annotation(ctx, "device", _device_id);
|
||||
tracing::add_perfetto_annotation(ctx, "tid", _tid);
|
||||
tracing::add_perfetto_annotation(ctx, "depth", _depth);
|
||||
tracing::add_perfetto_annotation(ctx, "corr_id", _corr_id);
|
||||
tracing::add_perfetto_annotation(ctx, "args",
|
||||
hip_api_string(_api_id, data));
|
||||
}
|
||||
});
|
||||
}
|
||||
if(get_use_timemory())
|
||||
{
|
||||
@@ -739,8 +773,13 @@ hip_api_callback(uint32_t domain, uint32_t cid, const void* callback_data, void*
|
||||
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
tracing::pop_perfetto_ts(category::rocm_hip{}, op_name, _ts, "end_ns",
|
||||
static_cast<uint64_t>(_ts));
|
||||
tracing::pop_perfetto_ts(
|
||||
category::rocm_hip{}, op_name, _ts, [&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "end_ns", _ts);
|
||||
}
|
||||
});
|
||||
}
|
||||
if(get_use_timemory())
|
||||
{
|
||||
@@ -916,14 +955,33 @@ hip_activity_callback(const char* begin, const char* end, void*)
|
||||
assert(_end_ns >= _beg_ns);
|
||||
tracing::push_perfetto_ts(
|
||||
category::device_hip{}, _kernel_names.at(_name).c_str(), _beg_ns,
|
||||
perfetto::Flow::ProcessScoped(_cid), "begin_ns", _beg_ns, "corr_id",
|
||||
record->correlation_id, "device", _devid, "queue", _queid, "pid",
|
||||
record->process_id, "tid", _tid, "op", _op_id_names.at(record->op));
|
||||
tracing::pop_perfetto_ts(category::device_hip{}, "", _end_ns, "end_ns",
|
||||
_end_ns);
|
||||
perfetto::Flow::ProcessScoped(_cid), [&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "begin_ns", _beg_ns);
|
||||
tracing::add_perfetto_annotation(ctx, "corr_id", _corr_id);
|
||||
tracing::add_perfetto_annotation(ctx, "device", _devid);
|
||||
tracing::add_perfetto_annotation(ctx, "queue", _queid);
|
||||
tracing::add_perfetto_annotation(ctx, "tid", _tid);
|
||||
tracing::add_perfetto_annotation(ctx, "op",
|
||||
_op_id_names.at(record->op));
|
||||
}
|
||||
});
|
||||
tracing::pop_perfetto_ts(
|
||||
category::device_hip{}, "", _end_ns, [&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "end_ns", _end_ns);
|
||||
}
|
||||
});
|
||||
// for some reason, this is necessary to make sure very last one ends
|
||||
tracing::pop_perfetto_ts(category::device_hip{}, "", _end_ns, "end_ns",
|
||||
_end_ns);
|
||||
tracing::pop_perfetto_ts(
|
||||
category::device_hip{}, "", _end_ns, [&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "end_ns", _end_ns);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(_critical_trace)
|
||||
|
||||
@@ -823,7 +823,13 @@ post_process_perfetto(int64_t _tid, const bundle_t* _init,
|
||||
_init->get<backtrace_timestamp>()->get_timestamp(), _beg_ns);
|
||||
|
||||
tracing::push_perfetto_ts(category::sampling{}, "samples [omnitrace]", _beg_ns,
|
||||
"begin_ns", _beg_ns);
|
||||
[&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(
|
||||
ctx, "begin_ns", _beg_ns);
|
||||
}
|
||||
});
|
||||
|
||||
auto _as_hex = [](auto _v) { return JOIN("", "0x", std::hex, _v); };
|
||||
|
||||
@@ -855,13 +861,24 @@ post_process_perfetto(int64_t _tid, const bundle_t* _init,
|
||||
tracing::push_perfetto_ts(
|
||||
category::sampling{}, _name, _beg,
|
||||
[&](perfetto::EventContext ctx) {
|
||||
tracing::add_perfetto_annotation(ctx, "begin_ns", _beg);
|
||||
tracing::add_perfetto_annotation(ctx, "lineinfo", _info);
|
||||
tracing::add_perfetto_annotation(ctx, "inlined",
|
||||
(_n++ > 0));
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "begin_ns",
|
||||
_beg);
|
||||
tracing::add_perfetto_annotation(ctx, "lineinfo",
|
||||
_info);
|
||||
tracing::add_perfetto_annotation(ctx, "inlined",
|
||||
(_n++ > 0));
|
||||
}
|
||||
});
|
||||
tracing::pop_perfetto_ts(
|
||||
category::sampling{}, _name, _end,
|
||||
[&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "end_ns", _end);
|
||||
}
|
||||
});
|
||||
tracing::pop_perfetto_ts(category::sampling{}, _name, _end,
|
||||
"end_ns", _end);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -870,38 +887,53 @@ post_process_perfetto(int64_t _tid, const bundle_t* _init,
|
||||
tracing::push_perfetto_ts(
|
||||
category::sampling{}, _name, _beg,
|
||||
[&](perfetto::EventContext ctx) {
|
||||
tracing::add_perfetto_annotation(ctx, "begin_ns", _beg);
|
||||
tracing::add_perfetto_annotation(ctx, "file", iitr.location);
|
||||
tracing::add_perfetto_annotation(ctx, "pc",
|
||||
_as_hex(iitr.address));
|
||||
tracing::add_perfetto_annotation(ctx, "line_address",
|
||||
_as_hex(iitr.line_address));
|
||||
|
||||
if(iitr.lineinfo)
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
auto _lines = iitr.lineinfo.lines;
|
||||
std::reverse(_lines.begin(), _lines.end());
|
||||
size_t _n = 0;
|
||||
for(const auto& litr : _lines)
|
||||
tracing::add_perfetto_annotation(ctx, "begin_ns", _beg);
|
||||
tracing::add_perfetto_annotation(ctx, "file",
|
||||
iitr.location);
|
||||
tracing::add_perfetto_annotation(ctx, "pc",
|
||||
_as_hex(iitr.address));
|
||||
tracing::add_perfetto_annotation(
|
||||
ctx, "line_address", _as_hex(iitr.line_address));
|
||||
if(iitr.lineinfo)
|
||||
{
|
||||
auto _label = JOIN('-', "lineinfo", _n++);
|
||||
tracing::add_perfetto_annotation(
|
||||
ctx, _label.c_str(),
|
||||
JOIN('@', demangle(litr.name),
|
||||
JOIN(':', litr.location, litr.line)));
|
||||
auto _lines = iitr.lineinfo.lines;
|
||||
std::reverse(_lines.begin(), _lines.end());
|
||||
size_t _n = 0;
|
||||
for(const auto& litr : _lines)
|
||||
{
|
||||
auto _label = JOIN('-', "lineinfo", _n++);
|
||||
tracing::add_perfetto_annotation(
|
||||
ctx, _label.c_str(),
|
||||
JOIN('@', demangle(litr.name),
|
||||
JOIN(':', litr.location, litr.line)));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tracing::pop_perfetto_ts(category::sampling{}, _name, _end, "end_ns",
|
||||
_end);
|
||||
tracing::pop_perfetto_ts(category::sampling{}, _name, _end,
|
||||
[&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(
|
||||
ctx, "end_ns", _end);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
_last_ts = _bt_ts->get_timestamp();
|
||||
}
|
||||
|
||||
tracing::pop_perfetto_ts(category::sampling{}, "samples [omnitrace]", _end_ns,
|
||||
"end_ns", _end_ns);
|
||||
[&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "end_ns",
|
||||
_end_ns);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
auto _processing_thread = threading::get_tid();
|
||||
|
||||
@@ -31,9 +31,12 @@
|
||||
#include "library/runtime.hpp"
|
||||
#include "library/sampling.hpp"
|
||||
#include "library/timemory.hpp"
|
||||
#include "library/tracing/annotation.hpp"
|
||||
#include "library/utility.hpp"
|
||||
|
||||
#include <timemory/components/timing/backends.hpp>
|
||||
#include <timemory/hash/types.hpp>
|
||||
#include <timemory/mpl/type_traits.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
@@ -159,43 +162,43 @@ template <typename CategoryT, typename... Args>
|
||||
inline void
|
||||
push_timemory(CategoryT, const char* name, Args&&... args)
|
||||
{
|
||||
if(trait::runtime_enabled<CategoryT>::get())
|
||||
{
|
||||
auto& _data = tracing::get_instrumentation_bundles();
|
||||
// this generates a hash for the raw string array
|
||||
auto _hash = tim::add_hash_id(tim::string_view_t{ name });
|
||||
auto* _bundle = _data.allocator.allocate(1);
|
||||
_data.bundles.emplace_back(_bundle);
|
||||
_data.allocator.construct(_bundle, _hash);
|
||||
_bundle->start(std::forward<Args>(args)...);
|
||||
}
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
auto& _data = tracing::get_instrumentation_bundles();
|
||||
// this generates a hash for the raw string array
|
||||
auto _hash = tim::add_hash_id(tim::string_view_t{ name });
|
||||
auto* _bundle = _data.allocator.allocate(1);
|
||||
_data.bundles.emplace_back(_bundle);
|
||||
_data.allocator.construct(_bundle, _hash);
|
||||
_bundle->start(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename CategoryT, typename... Args>
|
||||
inline void
|
||||
pop_timemory(CategoryT, const char* name, Args&&... args)
|
||||
{
|
||||
if(trait::runtime_enabled<CategoryT>::get())
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
auto _hash = tim::hash::get_hash_id(tim::string_view_t{ name });
|
||||
auto& _data = tracing::get_instrumentation_bundles();
|
||||
if(_data.bundles.empty())
|
||||
{
|
||||
auto _hash = tim::hash::get_hash_id(tim::string_view_t{ name });
|
||||
auto& _data = tracing::get_instrumentation_bundles();
|
||||
if(_data.bundles.empty())
|
||||
OMNITRACE_DEBUG("[%s] skipped %s :: empty bundle stack\n", "omnitrace_pop_trace",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
for(size_t i = _data.bundles.size(); i > 0; --i)
|
||||
{
|
||||
auto*& _v = _data.bundles.at(i - 1);
|
||||
if(_v->get_hash() == _hash)
|
||||
{
|
||||
OMNITRACE_DEBUG("[%s] skipped %s :: empty bundle stack\n",
|
||||
"omnitrace_pop_trace", name);
|
||||
return;
|
||||
}
|
||||
for(size_t i = _data.bundles.size(); i > 0; --i)
|
||||
{
|
||||
auto*& _v = _data.bundles.at(i - 1);
|
||||
if(_v->get_hash() == _hash)
|
||||
{
|
||||
_v->stop(std::forward<Args>(args)...);
|
||||
_data.allocator.destroy(_v);
|
||||
_data.allocator.deallocate(_v, 1);
|
||||
_data.bundles.erase(_data.bundles.begin() + (i - 1));
|
||||
break;
|
||||
}
|
||||
_v->stop(std::forward<Args>(args)...);
|
||||
_data.allocator.destroy(_v);
|
||||
_data.allocator.deallocate(_v, 1);
|
||||
_data.bundles.erase(_data.bundles.begin() + (i - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,24 +207,78 @@ template <typename CategoryT, typename... Args>
|
||||
inline void
|
||||
push_perfetto(CategoryT, const char* name, Args&&... args)
|
||||
{
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
uint64_t _ts = comp::wall_clock::record();
|
||||
TRACE_EVENT_BEGIN(trait::name<CategoryT>::value, perfetto::StaticString(name), _ts,
|
||||
"begin_ns", _ts, std::forward<Args>(args)...);
|
||||
if constexpr(sizeof...(Args) == 1 &&
|
||||
std::is_invocable<Args..., perfetto::EventContext>::value)
|
||||
{
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
TRACE_EVENT_BEGIN(trait::name<CategoryT>::value, perfetto::StaticString(name),
|
||||
_ts, "begin_ns", _ts, std::forward<Args>(args)...);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_EVENT_BEGIN(trait::name<CategoryT>::value, perfetto::StaticString(name),
|
||||
_ts, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_EVENT_BEGIN(trait::name<CategoryT>::value, perfetto::StaticString(name),
|
||||
_ts, std::forward<Args>(args)...,
|
||||
[&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "begin_ns", _ts);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename CategoryT, typename... Args>
|
||||
inline void
|
||||
pop_perfetto(CategoryT, const char*, Args&&... args)
|
||||
{
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
uint64_t _ts = comp::wall_clock::record();
|
||||
TRACE_EVENT_END(trait::name<CategoryT>::value, _ts, "end_ns", _ts,
|
||||
std::forward<Args>(args)...);
|
||||
if constexpr(sizeof...(Args) == 1 &&
|
||||
std::is_invocable<Args..., perfetto::EventContext>::value)
|
||||
{
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
TRACE_EVENT_END(trait::name<CategoryT>::value, _ts, "end_ns", _ts,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_EVENT_END(trait::name<CategoryT>::value, _ts,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_EVENT_END(trait::name<CategoryT>::value, _ts, std::forward<Args>(args)...,
|
||||
[&](perfetto::EventContext ctx) {
|
||||
if(config::get_perfetto_annotations())
|
||||
{
|
||||
tracing::add_perfetto_annotation(ctx, "end_ns", _ts);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename CategoryT, typename... Args>
|
||||
inline void
|
||||
push_perfetto_ts(CategoryT, const char* name, uint64_t _ts, Args&&... args)
|
||||
{
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
TRACE_EVENT_BEGIN(trait::name<CategoryT>::value, perfetto::StaticString(name), _ts,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
@@ -230,6 +287,9 @@ template <typename CategoryT, typename... Args>
|
||||
inline void
|
||||
pop_perfetto_ts(CategoryT, const char*, uint64_t _ts, Args&&... args)
|
||||
{
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<CategoryT>::get()) return;
|
||||
|
||||
TRACE_EVENT_END(trait::name<CategoryT>::value, _ts, std::forward<Args>(args)...);
|
||||
}
|
||||
} // namespace tracing
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "api.hpp"
|
||||
#include "library/categories.hpp"
|
||||
#include "library/components/category_region.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/tracing.hpp"
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ == 7)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace impl
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <size_t Idx, size_t... Tail>
|
||||
void
|
||||
invoke_category_region_start(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count, std::index_sequence<Idx, Tail...>)
|
||||
{
|
||||
static_assert(Idx > OMNITRACE_CATEGORY_NONE && Idx < OMNITRACE_CATEGORY_LAST,
|
||||
"Error! index sequence should only contain values which are greater "
|
||||
"than OMNITRACE_CATEGORY_NONE and less than OMNITRACE_CATEGORY_LAST");
|
||||
|
||||
if(_category == Idx)
|
||||
{
|
||||
using category_type = category_type_id_t<Idx>;
|
||||
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<category_type>::get()) return;
|
||||
|
||||
component::category_region<category_type>::start(
|
||||
name, [&](::perfetto::EventContext ctx) {
|
||||
if(_annotations && config::get_perfetto_annotations())
|
||||
{
|
||||
for(size_t i = 0; i < _annotation_count; ++i)
|
||||
tracing::add_perfetto_annotation(ctx, _annotations[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr size_t remaining = sizeof...(Tail);
|
||||
if constexpr(remaining > 0)
|
||||
invoke_category_region_start(_category, name, _annotations, _annotation_count,
|
||||
std::index_sequence<Tail...>{});
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t Idx, size_t... Tail>
|
||||
void
|
||||
invoke_category_region_stop(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count, std::index_sequence<Idx, Tail...>)
|
||||
{
|
||||
static_assert(Idx > OMNITRACE_CATEGORY_NONE && Idx < OMNITRACE_CATEGORY_LAST,
|
||||
"Error! index sequence should only contain values which are greater "
|
||||
"than OMNITRACE_CATEGORY_NONE and less than OMNITRACE_CATEGORY_LAST");
|
||||
|
||||
if(_category == Idx)
|
||||
{
|
||||
using category_type = category_type_id_t<Idx>;
|
||||
|
||||
// skip if category is disabled
|
||||
if(!trait::runtime_enabled<category_type>::get()) return;
|
||||
|
||||
component::category_region<category_type>::stop(
|
||||
name, [&](::perfetto::EventContext ctx) {
|
||||
if(_annotations && config::get_perfetto_annotations())
|
||||
{
|
||||
for(size_t i = 0; i < _annotation_count; ++i)
|
||||
tracing::add_perfetto_annotation(ctx, _annotations[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr size_t remaining = sizeof...(Tail);
|
||||
if constexpr(remaining > 0)
|
||||
invoke_category_region_stop(_category, name, _annotations, _annotation_count,
|
||||
std::index_sequence<Tail...>{});
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
} // namespace impl
|
||||
} // namespace omnitrace
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_trace_hidden(const char* name)
|
||||
{
|
||||
omnitrace::component::category_region<omnitrace::category::host>::start(name);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_trace_hidden(const char* name)
|
||||
{
|
||||
omnitrace::component::category_region<omnitrace::category::host>::stop(name);
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
///
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_region_hidden(const char* name)
|
||||
{
|
||||
omnitrace::component::category_region<omnitrace::category::user>::start(name);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_region_hidden(const char* name)
|
||||
{
|
||||
omnitrace::component::category_region<omnitrace::category::user>::stop(name);
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
///
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_category_region_hidden(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
omnitrace::impl::invoke_category_region_start(
|
||||
_category, name, _annotations, _annotation_count,
|
||||
omnitrace::utility::make_index_sequence_range<1, OMNITRACE_CATEGORY_LAST>{});
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_category_region_hidden(omnitrace_category_t _category, const char* name,
|
||||
omnitrace_annotation_t* _annotations,
|
||||
size_t _annotation_count)
|
||||
{
|
||||
omnitrace::impl::invoke_category_region_stop(
|
||||
_category, name, _annotations, _annotation_count,
|
||||
omnitrace::utility::make_index_sequence_range<1, OMNITRACE_CATEGORY_LAST>{});
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ == 7)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
Viittaa uudesa ongelmassa
Block a user