mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
Debug macros for easy performance profiling
The debug macros 'GENODE_LOG_TSC' and 'GENODE_LOG_TSC_NAMED' allow for the easy gathering of the TSC ticks consumed by the calling scope. Fixes #4066
This commit is contained in:
parent
ac07f9d08e
commit
99f4b3cd07
@ -19,10 +19,10 @@
|
|||||||
#include <trace/timestamp.h>
|
#include <trace/timestamp.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Log;
|
class Log;
|
||||||
class Raw;
|
class Raw;
|
||||||
class Trace_output;
|
class Trace_output;
|
||||||
|
class Log_tsc_probe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -184,4 +184,144 @@ namespace Genode {
|
|||||||
Trace_output::trace_output().output(Trace::timestamp(), ": ", args...); }
|
Trace_output::trace_output().output(Trace::timestamp(), ": ", args...); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper for the 'GENODE_LOG_TSC' utility
|
||||||
|
*/
|
||||||
|
class Genode::Log_tsc_probe : Noncopyable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef Trace::Timestamp Timestamp;
|
||||||
|
|
||||||
|
struct Pretty_tsc
|
||||||
|
{
|
||||||
|
Timestamp value;
|
||||||
|
|
||||||
|
void print(Output &out) const
|
||||||
|
{
|
||||||
|
Timestamp const K = 1000, M = 1000*K, G = 1000*M;
|
||||||
|
|
||||||
|
using Genode::print;
|
||||||
|
|
||||||
|
if (value > 100*G) print(out, value/G, "G");
|
||||||
|
else if (value > 100*M) print(out, value/M, "M");
|
||||||
|
else if (value > 100*K) print(out, value/K, "K");
|
||||||
|
else print(out, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class Stats : Noncopyable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
friend class Log_tsc_probe;
|
||||||
|
|
||||||
|
/* rate of log messages in number of calls */
|
||||||
|
unsigned const _sample_rate;
|
||||||
|
|
||||||
|
Timestamp _tsc_sum = 0; /* accumulated TSC ticks spent */
|
||||||
|
unsigned _calls = 0; /* number of executions */
|
||||||
|
unsigned _cycle_count = 0; /* track sample rate */
|
||||||
|
unsigned _num_entered = 0; /* recursion depth */
|
||||||
|
Mutex _mutex { }; /* protect stats */
|
||||||
|
|
||||||
|
void enter()
|
||||||
|
{
|
||||||
|
Mutex::Guard guard(_mutex);
|
||||||
|
|
||||||
|
_num_entered++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void leave(char const * const name, Timestamp duration)
|
||||||
|
{
|
||||||
|
Mutex::Guard guard(_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the probed scope is executed recursively or
|
||||||
|
* concurrently by multiple threads, defer the accounting
|
||||||
|
* until the scope is completely left.
|
||||||
|
*/
|
||||||
|
_num_entered--;
|
||||||
|
if (_num_entered > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_tsc_sum = _tsc_sum + duration;
|
||||||
|
|
||||||
|
_calls++;
|
||||||
|
_cycle_count++;
|
||||||
|
|
||||||
|
if (_cycle_count < _sample_rate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
log(" TSC ", name, ": ", Pretty_tsc { _tsc_sum }, " "
|
||||||
|
"(", _calls, " calls, last ", Pretty_tsc { duration }, ")");
|
||||||
|
_cycle_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Stats(unsigned sample_rate) : _sample_rate(sample_rate) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Stats &_stats;
|
||||||
|
|
||||||
|
Timestamp const _start = Trace::timestamp();
|
||||||
|
|
||||||
|
struct { char const *_name; };
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Log_tsc_probe(Stats &stats, char const *name)
|
||||||
|
:
|
||||||
|
_stats(stats), _name(name)
|
||||||
|
{
|
||||||
|
_stats.enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Log_tsc_probe()
|
||||||
|
{
|
||||||
|
_stats.leave(_name, Trace::timestamp() - _start);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print TSC (time-stamp counter) ticks consumed by the calling function
|
||||||
|
*
|
||||||
|
* The macro captures the TSC ticks spent in the current scope and prints the
|
||||||
|
* statistics about the accumulated cycles spent and the total number of calls.
|
||||||
|
* For example,
|
||||||
|
*
|
||||||
|
* TSC apply_config: 7072M (52 calls, last 314M)
|
||||||
|
*
|
||||||
|
* When this line appears in the log, the 'apply_config' function was executed
|
||||||
|
* 52 times and consumed 7072 million TSC ticks. The last call took 314 million
|
||||||
|
* ticks.
|
||||||
|
*
|
||||||
|
* The argument 'n' specifies the amount of calls after which the statistics
|
||||||
|
* are printed. It allows for the tuning of the amount of output depending on
|
||||||
|
* the instrumented function.
|
||||||
|
*/
|
||||||
|
#define GENODE_LOG_TSC(n) \
|
||||||
|
static Genode::Log_tsc_probe::Stats genode_log_tsc_stats { n }; \
|
||||||
|
Genode::Log_tsc_probe genode_log_tsc_probe(genode_log_tsc_stats, __func__);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variant of 'GENODE_LOG_TSC' that accepts the name of the probe as argument
|
||||||
|
*
|
||||||
|
* This variant is useful to disambiguate multiple scopes within one function
|
||||||
|
* or when placing probes in methods that have the same name, e.g., overloads
|
||||||
|
* within the same class or same-named methods of different classes.
|
||||||
|
*/
|
||||||
|
#define GENODE_LOG_TSC_NAMED(n, name) \
|
||||||
|
static Genode::Log_tsc_probe::Stats genode_log_tsc_stats { n }; \
|
||||||
|
Genode::Log_tsc_probe genode_log_tsc_probe(genode_log_tsc_stats, name);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _INCLUDE__BASE__LOG_H_ */
|
#endif /* _INCLUDE__BASE__LOG_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user