C++ Utilities¶
Scope¶
A scope configuration handles how the component instances within a bundle
get inserted into the call-graph. The default behavior is scope::tree
.
This can be combined with scope::timeline
to form a hierarchical call-graph
where each entry is unique (lots of data): scope::config cfg = scope::tree{} + scope::timeline{}
.
When the scope::flat
is used, all component instances become a child
of the root node (i.e. the depth in call-stack is always zero). Similar
to scope::tree
, scope::flat
can be combined with scope::timeline
.
using bundle_t = tim::component_tuple<wall_clock>;
namespace scope = tim::scope;
void foo()
{
// always tree-scoped
auto a = bundle_t("foo", scope::tree{});
// always flat-scoped
auto b = bundle_t("foo", scope::flat{});
// always timeline-scoped
auto c = bundle_t("foo", scope::timeline{});
// subject to global settings for flat and timeline
auto c = bundle_t("foo", scope::config{});
}
-
struct config : public std::bitset<scope_count>¶
this data type encodes the options of storage scope. The default is hierarchical (tree) scope. Specification of flat scope overrides the hierarchy scope, e.g. you cannot have a hierarchical flat scope. The timeline scope is meaningless should a specification of tree or flat, thus the valid combinations are: tree, flat, tree + timeline, flat + timeline.
-
struct tree : public std::integral_constant<int, 2>¶
Dummy struct to designates tree (hierarchical) storage. This scope (default) maintains nesting in the call-graph storage. In this scoping mode, the results will be separated from each other based on the identifier AND the current number of component instances in a “start” region. E.g. for two components with the same identifiers where the first calls start, then the second calls start then the second will be at a depth of +1 relative to the first (i.e. a child of the first).
Subclassed by tim::quirk::tree_scope
-
struct flat : public std::integral_constant<int, 0>¶
Dummy struct to designates flat (no hierarchy) storage. When flat scoping is globally enabled, all entries to the call-graph storage at entered at a depth of zero. Thus, if you want a report of all the function calls and their total values for each identifier, flat scoping should be globally enabled. This can be combined with timeline scoping to produce results where every measurement is its own call-graph entry at a depth of zero (produces a large amount of data). Flat-scoping can be enabled at the component bundler level also, there are two ways to do this: (1) to enable flat-scoping for all instances of the bundle, add tim::quirk::flat_scope to the template parameters of the bundler; (2) to enable flat-scoping for specific bundler instances, pass.
as the second argument to the constructor of the bundle.tim::quirk::config<tim::quirk::flat_scope, ...>{}
Subclassed by tim::quirk::flat_scope
-
struct timeline : public std::integral_constant<int, 1>¶
Dummy struct to designates timeline (hierarchical, non-duplicated) storage. It is meaningless by itself and should be combined with tim::scope::tree or tim::scope::flat. A tree timeline has all the hierarchy properties of the tree scope but entries at the same depth with the same identifiers are separated entries in the resuls. Timeline-scoping can be enabled at the component bundler level also, there are two ways to do this: (1) to enable timeline-scoping for all instances of the bundle, add tim::quirk::timeline_scope to the template parameters of the bundler; (2) to enable timeline-scoping for specific bundler instances, pass.
as the second argument to the constructor of the bundle.tim::quirk::config<tim::quirk::timeline_scope, ...>{}
Subclassed by tim::quirk::timeline_scope
Quirks¶
Quirks are used to slightly tweak the default behavior of component bundlers.
Quirks can be included as template parameters and the property of the quirk will
be applied to all instances of that component bundle,
e.g. component_tuple<wall_clock, quirk::flat_scope>
will cause all instances
of that bundler to propagate the flat-storage specification to the wall-clock
component regardless of the global setting. Quirks can also be applied
per-component bundle instance within a tim::quirk::config<...>
specification, e.g.
an auto_list
traditionally invokes start()
on a component_list
in the constructor
and thus, any attempts to activate the components in the list after construction are
ignored. Thus, if a special initialization case is desired for a particular instance
of auto_list
, the quirk::explicit_start
can be added to suppress this behavior so
that initialization can be performed before manually invoking start()
.
namespace quirk = tim::quirk;
using bundle_t = tim::auto_list<wall_clock, cpu_clock>;
using quirk_t = quirk::config<quirk::explicit_start>;
void foo(bool condition)
{
auto f = bundle_t("foo", quirk_t{});
if(condition)
{
f.initialize<wall_clock>();
f.disable<cpu_clock>();
f.start();
}
// ...
}
void bar()
{
auto f = bundle_t("bar");
// ...
}
-
template<typename ...Types>
struct config¶ a variadic type which holds zero or more quirks that are passed to the constructor of a component bundler.
namespace quirk = tim::quirk; using foo_t = tim::component_tuple<wall_clock>; foo_t f("example", quirk::config<quirk::auto_start, quirk::flat_scope>{}); ... f.stop();
-
struct auto_start : public tim::concepts::quirk_type¶
Will cause non-auto bundlers to invoke start() during construction. If included as a template parameter of the bundler, it will have no effect. Usage:
bundler constructor w/in tim::quirk::config object
bundler template parameter
// usage as template parameter using bundle_t = tim::component_tuple<foo, tim::quirk::auto_start>; void bar() { using bundle_t = tim::component_tuple<foo>; // usage in constructor bundle_t obj{ "bar", tim::quirk::config<tim::quirk:auto_start>{} }; }
-
struct auto_stop : public tim::concepts::quirk_type¶
This quirk is irrelevant. This is the default behavior for all bundlers. See tim::quirk::explicit_stop to suppress this behavior.
-
struct explicit_start : public tim::concepts::quirk_type¶
Will cause auto bundlers to suppress calling start during construction. If included as a template parameter of the non-auto bundler, it will have no effect. Usage:
bundler constructor w/in tim::quirk::config object
bundler template parameter
// usage as template parameter using bundle_t = tim::auto_tuple<foo, tim::quirk::explicit_start>; void bar() { using bundle_t = tim::auto_tuple<foo>; // usage in constructor bundle_t obj{ "bar", tim::quirk::config<tim::quirk:explicit_start>{} }; obj.start(); // now required }
-
struct explicit_stop : public tim::concepts::quirk_type¶
Will cause bundlers to suppress calling stop during destruction. Usage:
bundler template parameter
// usage as template parameter using foo_bundle_t = tim::auto_tuple<foo, tim::quirk::explicit_stop>; using baz_bundle_t = tim::component_tuple<foo, tim::quirk::explicit_stop>;
-
struct explicit_push : public tim::concepts::quirk_type¶
Will suppress the implicit
push()
withinstart()
for the bundlers with this characteristic Usage:constructor of bundler within a tim::quirk::config object
bundler template parameter
// usage as template parameter using bundle_t = tim::component_tuple<foo, tim::quirk::explicit_push>;
-
struct explicit_pop : public tim::concepts::quirk_type¶
Will suppress the implicit
pop()
withinstop()
for the bundlers with this characteristic. Combining this with tim::quirk::explicit_push will effectively allow the measurements within the bundler to only be recorded locally and statistics to not be updated during intermediate measurements. Usage:bundler template parameter
// usage as template parameter using bundle_t = tim::component_tuple<tim::component::wall_clock, tim::quirk::explicit_push, tim::quirk::explicit_pop>; static bundle_t fibonacci_total{ "total" }; long fibonacci(long n) { bundle_t tmp{}; tmp.start(); auto result = (n < 2) ? n : (fibonacci(n-1) + fibonacci(n-2)); fibonacci_total += tmp.stop(); return result; } long foo(long n) { // create new "fibonacci_total" entry in call-graph. Pushing will reset // any previous measurements bundle_total.push(); // invoke this function when foo returns tim::scope::destructor _dtor{ []() { fibonacci_total.pop(); } }; return fibonacci(n); }
-
struct exit_report : public tim::concepts::quirk_type¶
Will cause auto-bundlers to write itself to stdout during destruction. Usage:
constructor of bundler within a tim::quirk::config object
bundler template parameter
-
struct no_init : public tim::concepts::quirk_type¶
Will cause bundlers to suppress calling any routines related to initializing routines during construction. This is useful to override the default-initializer for a bundler type Usage:
constructor of bundler within a tim::quirk::config object
bundler template parameter
-
struct no_store : public tim::concepts::quirk_type¶
Will cause bundlers to suppress any implicit entries into the component storage. This behavior is the default for tim::lightweight_bundle and is meaningless in that context. It is quite similar to adding both tim::quirk::explicit_push and tim::quirk::explicit_pop, however it effectively propagates tim::quirk::explicit_pop when used within the constructor. Usage:
constructor of bundler within a tim::quirk::config object
bundler template parameter
-
struct tree_scope : public tim::scope::tree, public tim::concepts::quirk_type¶
Will cause bundlers to ignore the global settings and enforce hierarchical storage in the call-graph. Usage:
constructor of bundler within a tim::quirk::config object
bundler template parameter
-
struct flat_scope : public tim::scope::flat, public tim::concepts::quirk_type¶
Will cause bundlers to ignore the global settings and enforce flat storage in the call-graph. Usage:
constructor of bundler within a tim::quirk::config object
bundler template parameter
-
struct timeline_scope : public tim::scope::timeline, public tim::concepts::quirk_type¶
Will cause bundlers to ignore the global settings and enforce timeline storage. Usage:
constructor of bundler within a tim::quirk::config object
bundler template parameter
Sampling¶
Typedefs
Enums
-
template<typename CompT, size_t N>
struct is_component<sampling::sampler<CompT, N>> : public true_type¶ - #include “timemory/sampling/sampler.hpp”
-
namespace tim¶
Extern template declarations
-
namespace sampling¶
Typedefs
-
template<size_t N>
using fixed_size_t = typename fixed_size<N>::type¶
Enums
-
template<size_t N>
struct fixed_size : public std::true_type¶ - #include “timemory/sampling/sampler.hpp”
-
template<>
struct fixed_size<dynamic> : public std::false_type¶ - #include “timemory/sampling/sampler.hpp”
-
template<int... Ids>
struct fixed_sig : public std::true_type¶ - #include “timemory/sampling/sampler.hpp”
-
template<>
struct fixed_sig<> : public std::false_type¶ - #include “timemory/sampling/sampler.hpp”
-
template<template<typename...> class CompT, size_t N, typename ...Types, int... SigIds>
struct sampler<CompT<Types...>, N, SigIds...> : public tim::component::base<sampler<CompT<Types...>, N, SigIds...>, void>, private tim::policy::instance_tracker<sampler<CompT<Types...>, N, SigIds...>, false>¶ - #include “timemory/sampling/sampler.hpp”
Public Types
-
using signal_set_t = std::set<int>¶
-
using pid_cb_t = std::function<bool(pid_t, int, int)>¶
-
using array_t = conditional_t<fixed_size_t<N>::value, std::array<components_t, N>, std::vector<components_t>>¶
-
using tracker_type = policy::instance_tracker<this_type, false>¶
Public Functions
-
template<typename Tp = fixed_size_t<N>, enable_if_t<Tp::value> = 0>
sampler(const std::string &_label, signal_set_t _good, signal_set_t _bad = signal_set_t{})¶
-
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value> = 0>
sampler(const std::string &_label, signal_set_t _good, signal_set_t _bad = signal_set_t{})¶
-
~sampler()¶
-
template<typename Tp = fixed_size_t<N>, enable_if_t<Tp::value> = 0>
void sample()¶
-
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value> = 0>
void sample()¶
-
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t<Tp::value> = 0>
void start()¶
-
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t<Tp::value> = 0>
void stop()¶
-
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t<!Tp::value> = 0>
void start()¶
-
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t<!Tp::value> = 0>
void stop()¶
-
inline bool is_good(int v) const¶
-
inline bool is_bad(int v) const¶
-
inline auto good_count() const¶
-
inline auto bad_count() const¶
-
inline auto count() const¶
-
inline auto &get_good()¶
-
inline auto &get_bad()¶
-
inline const auto &get_good() const¶
-
inline const auto &get_bad() const¶
-
inline auto backtrace_enabled() const¶
-
inline void enable_backtrace(bool val)¶
-
inline components_t *&get_last()¶
-
inline components_t *get_last() const¶
-
inline components_t *&get_latest()¶
-
inline components_t *get_latest() const¶
-
template<typename Tp = fixed_size_t<N>, enable_if_t<Tp::value> = 0>
components_t &get(size_t idx)¶
-
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value> = 0>
components_t &get(size_t idx)¶
-
template<typename Tp = fixed_size_t<N>, enable_if_t<Tp::value> = 0>
const components_t &get(size_t idx) const¶
-
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value> = 0>
const components_t &get(size_t idx) const¶
Public Static Functions
-
static void execute(int signum)¶
-
static void execute(int signum, siginfo_t*, void*)¶
-
static inline auto &get_samplers()¶
-
static inline auto get_latest_samples()¶
-
static void configure(std::set<int> _signals, int _verbose = 1)¶
Set up the sampler.
- Parameters
_signals – [in] A set of signals to catch
_verb – [in] Logging Verbosity
-
static inline void configure(int _signal = SIGALRM, int _verbose = 1)¶
-
static inline void ignore(const std::set<int> &_signals)¶
Ignore the signals.
- Parameters
_signals – [in] Set of signals
-
static inline void clear()¶
Clear all signals. Recommended to call ignore() prior to clearing all the signals.
-
static inline void pause()¶
Pause until a signal is delivered.
-
template<typename Func = pid_cb_t>
static int wait(pid_t _pid, int _verbose, bool _debug, Func &&_callback = pid_callback())¶ Wait function with an optional user callback of type:
where ‘a’ is the status, ‘b’ is the error value, and returns true if waiting should continuebool (*)(int a, int b)
- Parameters
_pid – [in] Process id to wait on
_verb – [in] Logging verbosity
_debug – [in] Enable debug logging
_cb – [in] Callback for checking whether to exit
-
template<typename Func = pid_cb_t>
static inline int wait(int _verbose = settings::verbose(), bool _debug = settings::debug(), Func &&_callback = pid_callback())¶
-
template<typename Func, enable_if_t<std::is_function<Func>::value> = 0>
static inline int wait(pid_t _pid, Func &&_callback, int _verbose = settings::verbose(), bool _debug = settings::debug())¶
-
template<typename Func, enable_if_t<std::is_function<Func>::value> = 0>
static inline int wait(Func &&_callback, int _verbose = settings::verbose(), bool _debug = settings::debug())¶
-
static inline void set_flags(int _flags)¶
Set the sigaction flags, e.g. SA_RESTART | SA_SIGINFO.
- Parameters
flags[in] – the sigaction flags to use
-
static void set_delay(double fdelay)¶
Value, expressed in seconds, that sets the length of time the sampler waits before starting sampling of the relevant measurements.
-
static void set_frequency(double ffreq)¶
-
static inline void set_rate(double frate)¶
Value, expressed in number of interupts per second, that configures the frequency that the sampler samples the relevant measurements.
-
static int get_itimer(int _signal)¶
Returns the itimer value associated with the given signal.
-
static bool check_itimer(int _stat, bool _throw_exception = false)¶
Checks to see if there was an error setting or getting itimer val.
Protected Attributes
-
bool m_backtrace = false¶
-
size_t m_idx = 0¶
-
components_t *m_last = nullptr¶
-
signal_set_t m_good = {}¶
-
signal_set_t m_bad = {}¶
Private Static Functions
-
static inline persistent_data &get_persistent_data()¶
-
struct persistent_data¶
Public Members
-
bool m_active = false¶
-
int m_flags = SA_RESTART | SA_SIGINFO¶
-
double m_delay = 0.001¶
-
double m_freq = 1.0 / 2.0¶
-
sigaction_t m_custom_sigaction¶
-
itimerval_t m_custom_itimerval = {{1, 0}, {0, units::msec}}¶
-
sigaction_t m_original_sigaction¶
-
itimerval_t m_original_itimerval¶
-
std::set<int> m_signals = {}¶
-
bool m_active = false¶
-
using signal_set_t = std::set<int>¶
-
template<size_t N>
-
namespace trait¶
- template<typename CompT, size_t N> sampler< CompT, N > > : public true_type
- #include “timemory/sampling/sampler.hpp”
-
namespace sampling¶