Add BoolProfiler and IntProfiler clases (using StackTraceProfiler)

A BoolProfiler uses two StackTraceProfilers to take profiled samples of
a boolean value.  At shutdown it prints the %false, %true, and a profile
for each case.

An IntProfiler is similar, but profiles buckets of 0, 1, 2, 4, and 5+.
Esse commit está contido em:
Edwin Smith
2013-06-30 11:17:10 -07:00
commit de Sara Golemon
commit 1532dd8597
2 arquivos alterados com 107 adições e 10 exclusões
+77 -5
Ver Arquivo
@@ -21,9 +21,13 @@
namespace HPHP {
const bool enable = getenv("STACKTRACE_PROFILER") != nullptr;
const bool enabled = getenv("STACKTRACE_PROFILER") != nullptr;
const int kMaxDepth = 10;
StackTraceProfiler::StackTraceProfiler(std::string name, int skip) :
m_name(name), finishing(false), m_root(nullptr), m_skip(skip) {
}
// Make a new caller node and link it into n's caller list.
StackTraceProfiler::Node* StackTraceProfiler::makeCaller(Node* n, void* addr) {
Node* caller = new (m_arena) Node(addr);
@@ -54,7 +58,7 @@ StackTraceProfiler::Node* StackTraceProfiler::findCaller(Node* n, void* addr) {
}
void StackTraceProfiler::count() {
if (!enable) return;
if (!enabled || finishing) return;
void* addrs[kMaxDepth];
auto count = backtrace(addrs, kMaxDepth);
if (count <= 0) return;
@@ -80,12 +84,12 @@ int StackTraceProfiler::numLeaves(Node* n) {
}
void StackTraceProfiler::print(Node* n, std::string indent) {
fprintf(stderr, "%s%d ", indent.c_str(), n->hits);
fprintf(stderr, "%s%lu ", indent.c_str(), n->hits);
if (n->addr) {
std::string s = StackTrace::Translate(n->addr)->toString();
fprintf(stderr, "%s\n", s.c_str());
} else {
fprintf(stderr, "%s\n", m_name);
fprintf(stderr, "%s\n", m_name.c_str());
}
if (numLeaves(n) <= 1) return;
indent += " ";
@@ -100,8 +104,76 @@ void StackTraceProfiler::print(Node* n, std::string indent) {
}
StackTraceProfiler::~StackTraceProfiler() {
if (!enable) return;
if (!enabled) return;
finishing = true;
print(&m_root, "");
}
BoolProfiler::BoolProfiler(std::string name)
: name(name)
, p1(name + "=true", 2)
, p0(name + "=false", 2)
{}
BoolProfiler::~BoolProfiler() {
if (!enabled) return;
auto total = p0.hits() + p1.hits();
if (total) {
fprintf(stderr, "%s: total=%lu false=%.1f%% true=%.1f%%\n", name.c_str(),
total,
100.0 * p0.hits() / total,
100.0 * p1.hits() / total);
}
}
bool BoolProfiler::operator()(bool b) {
(b ? &p1 : &p0)->count();
return b;
}
IntProfiler::IntProfiler(std::string name)
: name(name)
, pN(name + ">=65", 2)
, p64(name + "=33-64", 2)
, p32(name + "=17-32", 2)
, p16(name + "=9-16", 2)
, p8(name + "=5-8", 2)
, p4(name + "=3-4", 2)
, p2(name + "=2", 2)
, p1(name + "=1", 2)
, p0(name + "=0", 2)
{}
IntProfiler::~IntProfiler() {
if (!enabled) return;
auto total = p0.hits() + p1.hits() + p2.hits() + p4.hits() + p8.hits() +
p16.hits() + p32.hits() + p64.hits() + pN.hits();
if (total) {
fprintf(stderr, "%s: total=%lu 0=%.1f%% 1=%.1f%% 2=%.1f%% "
"3-4=%.1f%% 5-8=%.1f%% 9-16=%.1f%% 17-32=%.1f%% 33-64=%.1f%% "
"65+=%.1f%%\n", name.c_str(), total,
100.0 * p0.hits() / total,
100.0 * p1.hits() / total,
100.0 * p2.hits() / total,
100.0 * p4.hits() / total,
100.0 * p8.hits() / total,
100.0 * p16.hits() / total,
100.0 * p32.hits() / total,
100.0 * p64.hits() / total,
100.0 * pN.hits() / total);
}
}
void IntProfiler::operator()(unsigned i) {
(i == 0 ? &p0 :
i == 1 ? &p1 :
i == 2 ? &p2 :
i <= 4 ? &p4 :
i <= 8 ? &p8 :
i <= 16 ? &p16 :
i <= 32 ? &p32 :
i <= 64 ? &p64 :
&pN)->count();
}
}
+30 -5
Ver Arquivo
@@ -47,19 +47,18 @@ class StackTraceProfiler {
void* const addr;
Node* callers;
Node* next;
int hits;
size_t hits;
};
public:
explicit StackTraceProfiler(const char* name, int skip = 1) :
m_name(name), m_root(nullptr), m_skip(skip) {
}
explicit StackTraceProfiler(std::string name, int skip = 1);
~StackTraceProfiler();
StackTraceProfiler(const StackTraceProfiler& other) = delete;
StackTraceProfiler& operator=(const StackTraceProfiler& other) = delete;
// count one call in this probe.
void count();
size_t hits() const { return m_root.hits; }
private:
static bool compareNodes(Node* a, Node* b);
@@ -70,12 +69,38 @@ private:
private:
Arena m_arena;
const char* m_name;
const std::string m_name;
std::mutex m_mutex;
std::atomic<bool> finishing;
Node m_root;
int m_skip;
};
/*
* BoolProfiler is used to collect profiled samples of a bool variable.
*/
struct BoolProfiler {
explicit BoolProfiler(std::string name);
~BoolProfiler();
bool operator()(bool b);
private:
const std::string name;
StackTraceProfiler p1, p0;
};
/*
* IntProfiler is used to collect profiled samples of an unsiged variable.
* A histogram of samples are collected in power-of-2 buckets up to 64.
*/
struct IntProfiler {
explicit IntProfiler(std::string name);
~IntProfiler();
void operator()(unsigned i);
private:
const std::string name;
StackTraceProfiler pN, p64, p32, p16, p8, p4, p2, p1, p0;
};
}
#endif