Individual perfetto debug annotations (#157)
- instead of args="<list-of-string>" in perfetto, each argument is added
individually, enabling matching pointer values, etc.
## Previous behavior
Previously, all function arguments were wrapped into a single string,
e.g.:

## New Behavior
With the exception of the HIP API (whose args are provided as a single
string via `hipApiString`), all functions from MPI, RCCL, pthreads, etc.
have individual arguments in perfetto, e.g.:

In the above, previously, this would have been:
| | |
| - | - |
| args | `pthread_rwlock_t*=0x1c1cc50` |
The key benefit enabled is the ability to find slices with same arg
values:
<img width="753" alt="Screen Shot 2022-09-12 at 11 59 18 PM"
src="https://user-images.githubusercontent.com/6001865/189812915-0342f841-e5ce-4f8e-8169-0cb52f3425b5.png">
Previously, the entire "args" field would have had to match, which
essentially never happened if the pointer was used in two different
functions with different function signatures
## Example


[ROCm/rocprofiler-systems commit: 4ed8f8f762]
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
3e69264431
Коммит
63a999481c
поставляемый
+1
-1
Submodule projects/rocprofiler-systems/external/timemory updated: 69a6c7ad9d...05438aaf0f
+8
-8
@@ -248,10 +248,10 @@ void
|
||||
category_region<CategoryT>::audit(const gotcha_data_t& _data, audit::incoming,
|
||||
Args&&... _args)
|
||||
{
|
||||
start<OptsT...>(
|
||||
_data.tool_id.c_str(), "args",
|
||||
JOIN(", ",
|
||||
JOIN('=', tim::try_demangle<std::remove_reference_t<Args>>(), _args)...));
|
||||
start<OptsT...>(_data.tool_id.c_str(), [&](perfetto::EventContext ctx) {
|
||||
OMNITRACE_FOLD_EXPRESSION(tracing::add_perfetto_annotation(
|
||||
ctx, tim::try_demangle<std::remove_reference_t<Args>>(), _args));
|
||||
});
|
||||
}
|
||||
|
||||
template <typename CategoryT>
|
||||
@@ -269,10 +269,10 @@ void
|
||||
category_region<CategoryT>::audit(std::string_view _name, audit::incoming,
|
||||
Args&&... _args)
|
||||
{
|
||||
start<OptsT...>(
|
||||
_name.data(), "args",
|
||||
JOIN(", ",
|
||||
JOIN('=', tim::try_demangle<std::remove_reference_t<Args>>(), _args)...));
|
||||
start<OptsT...>(_name.data(), [&](perfetto::EventContext ctx) {
|
||||
OMNITRACE_FOLD_EXPRESSION(tracing::add_perfetto_annotation(
|
||||
ctx, tim::try_demangle<std::remove_reference_t<Args>>(), _args));
|
||||
});
|
||||
}
|
||||
|
||||
template <typename CategoryT>
|
||||
|
||||
@@ -64,5 +64,22 @@ struct is_optional : std::false_type
|
||||
template <typename Tp>
|
||||
struct is_optional<std::optional<Tp>> : std::true_type
|
||||
{};
|
||||
|
||||
template <typename Tp>
|
||||
struct can_stringify
|
||||
{
|
||||
private:
|
||||
static constexpr auto sfinae(int)
|
||||
-> decltype(std::declval<std::ostream&>() << std::declval<Tp>(), bool())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr auto sfinae(long) { return false; }
|
||||
|
||||
public:
|
||||
static constexpr bool value = sfinae(0);
|
||||
constexpr auto operator()() const { return sfinae(0); }
|
||||
};
|
||||
} // namespace concepts
|
||||
} // namespace tim
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "library/common.hpp"
|
||||
#include "library/concepts.hpp"
|
||||
#include "library/config.hpp"
|
||||
#include "library/debug.hpp"
|
||||
#include "library/defines.hpp"
|
||||
@@ -34,6 +35,8 @@
|
||||
|
||||
#include <timemory/components/timing/backends.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace tracing
|
||||
@@ -194,13 +197,74 @@ pop_timemory(CategoryT, const char* name, Args&&... args)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Np, typename Tp>
|
||||
auto
|
||||
add_perfetto_annotation(perfetto::EventContext& ctx, Np&& _name, Tp&& _val)
|
||||
{
|
||||
using named_type = std::remove_reference_t<std::remove_cv_t<std::decay_t<Np>>>;
|
||||
using value_type = std::remove_reference_t<std::remove_cv_t<std::decay_t<Tp>>>;
|
||||
|
||||
static_assert(concepts::is_string_type<named_type>::value,
|
||||
"Error! name is not a string type");
|
||||
|
||||
auto _get_dbg = [&]() {
|
||||
auto* _dbg = ctx.event()->add_debug_annotations();
|
||||
_dbg->set_name(std::string_view{ std::forward<Np>(_name) }.data());
|
||||
return _dbg;
|
||||
};
|
||||
|
||||
if constexpr(std::is_same<value_type, std::string_view>::value)
|
||||
{
|
||||
_get_dbg()->set_string_value(_val.data());
|
||||
}
|
||||
else if constexpr(concepts::is_string_type<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_string_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else if constexpr(std::is_same<value_type, bool>::value)
|
||||
{
|
||||
_get_dbg()->set_bool_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else if constexpr(std::is_enum<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_int_value(static_cast<int64_t>(std::forward<Tp>(_val)));
|
||||
}
|
||||
else if constexpr(std::is_floating_point<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_double_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else if constexpr(std::is_integral<value_type>::value)
|
||||
{
|
||||
if constexpr(std::is_unsigned<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_uint_value(std::forward<Tp>(_val));
|
||||
}
|
||||
else
|
||||
{
|
||||
_get_dbg()->set_int_value(std::forward<Tp>(_val));
|
||||
}
|
||||
}
|
||||
else if constexpr(std::is_pointer<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_pointer_value(reinterpret_cast<uint64_t>(std::forward<Tp>(_val)));
|
||||
}
|
||||
else if constexpr(concepts::can_stringify<value_type>::value)
|
||||
{
|
||||
_get_dbg()->set_string_value(JOIN("", std::forward<Tp>(_val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_empty<value_type>::value, "Error! unsupported data type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename CategoryT, typename... Args>
|
||||
inline void
|
||||
push_perfetto(CategoryT, const char* name, Args&&... args)
|
||||
{
|
||||
uint64_t _ts = comp::wall_clock::record();
|
||||
TRACE_EVENT_BEGIN(trait::name<CategoryT>::value, perfetto::StaticString(name), _ts,
|
||||
std::forward<Args>(args)..., "begin_ns", _ts);
|
||||
"begin_ns", _ts, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename CategoryT, typename... Args>
|
||||
@@ -208,8 +272,8 @@ inline void
|
||||
pop_perfetto(CategoryT, const char*, Args&&... args)
|
||||
{
|
||||
uint64_t _ts = comp::wall_clock::record();
|
||||
TRACE_EVENT_END(trait::name<CategoryT>::value, _ts, std::forward<Args>(args)...,
|
||||
"end_ns", _ts);
|
||||
TRACE_EVENT_END(trait::name<CategoryT>::value, _ts, "end_ns", _ts,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename CategoryT, typename... Args>
|
||||
|
||||
Ссылка в новой задаче
Block a user