Commit 887d59a6 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Switch stats to cache the pointer directly

I would have expected this to help a bunch but it seems to actually hurt
parent 28df5108
......@@ -123,7 +123,7 @@ uint8_t* PystonMemoryManager::allocateSection(MemoryGroup& MemGroup, uintptr_t S
}
std::string stat_name = "mem_section_" + std::string(SectionName);
Stats::log(Stats::getStatId(stat_name), MB.size());
Stats::log(Stats::getStatCounter(stat_name), MB.size());
// Save this address as the basis for our next request
MemGroup.Near = MB;
......
......@@ -23,17 +23,6 @@ namespace pyston {
#if !DISABLE_STATS
#if STAT_TIMERS
extern "C" const char* getStatTimerNameById(int id) {
return Stats::getStatName(id).c_str();
}
extern "C" int getStatTimerId() {
return StatTimer::getStack()->getId();
}
extern "C" const char* getStatTimerName() {
return getStatTimerNameById(getStatTimerId());
}
__thread StatTimer* StatTimer::stack;
......@@ -50,42 +39,46 @@ StatTimer* StatTimer::swapStack(StatTimer* s, uint64_t at_time) {
}
#endif
std::vector<uint64_t>* Stats::counts;
std::unordered_map<int, std::string>* Stats::names;
std::unordered_map<uint64_t*, std::string>* Stats::names;
bool Stats::enabled;
timespec Stats::start_ts;
uint64_t Stats::start_tick;
StatCounter::StatCounter(const std::string& name) : id(Stats::getStatId(name)) {
StatCounter::StatCounter(const std::string& name) : counter(Stats::getStatCounter(name)) {
}
StatPerThreadCounter::StatPerThreadCounter(const std::string& name) {
char buf[80];
snprintf(buf, 80, "%s_t%ld", name.c_str(), pthread_self());
id = Stats::getStatId(buf);
counter = Stats::getStatCounter(buf);
}
int Stats::getStatId(const std::string& name) {
static std::vector<uint64_t*>* counts;
uint64_t* Stats::getStatCounter(const std::string& name) {
// hacky but easy way of getting around static constructor ordering issues for now:
static std::unordered_map<int, std::string> names;
static std::unordered_map<uint64_t*, std::string> names;
Stats::names = &names;
static std::vector<uint64_t> counts;
Stats::counts = &counts;
static std::unordered_map<std::string, int> made;
static std::unordered_map<std::string, uint64_t*> made;
// TODO: can do better than doing a malloc per counter:
static std::vector<uint64_t*> counts;
pyston::counts = &counts;
if (made.count(name))
return made[name];
int rtn = names.size();
uint64_t* rtn = new uint64_t(0);
names[rtn] = name;
made[name] = rtn;
counts.push_back(0);
counts.push_back(rtn);
return rtn;
}
std::string Stats::getStatName(int id) {
return (*names)[id];
void Stats::clear() {
assert(counts);
for (auto p : *counts) {
*p = 0;
}
}
void Stats::startEstimatingCPUFreq() {
......@@ -119,7 +112,7 @@ void Stats::dump(bool includeZeros) {
fprintf(stderr, "Counters:\n");
std::vector<std::pair<std::string, int>> pairs;
std::vector<std::pair<std::string, uint64_t*>> pairs;
for (const auto& p : *names) {
pairs.push_back(make_pair(p.second, p.first));
}
......@@ -129,19 +122,19 @@ void Stats::dump(bool includeZeros) {
uint64_t ticks_in_main = 0;
uint64_t accumulated_stat_timer_ticks = 0;
for (int i = 0; i < pairs.size(); i++) {
if (includeZeros || (*counts)[pairs[i].second] > 0) {
uint64_t count = *pairs[i].second;
if (includeZeros || count > 0) {
if (startswith(pairs[i].first, "us_") || startswith(pairs[i].first, "_init_us_")) {
fprintf(stderr, "%s: %lu\n", pairs[i].first.c_str(),
(uint64_t)((*counts)[pairs[i].second] / cycles_per_us));
fprintf(stderr, "%s: %lu\n", pairs[i].first.c_str(), (uint64_t)(count / cycles_per_us));
} else
fprintf(stderr, "%s: %lu\n", pairs[i].first.c_str(), (*counts)[pairs[i].second]);
fprintf(stderr, "%s: %lu\n", pairs[i].first.c_str(), count);
if (startswith(pairs[i].first, "us_timer_"))
accumulated_stat_timer_ticks += (*counts)[pairs[i].second];
accumulated_stat_timer_ticks += count;
if (pairs[i].first == "ticks_in_main")
ticks_in_main = (*counts)[pairs[i].second];
ticks_in_main = count;
}
}
......@@ -165,10 +158,10 @@ void Stats::dump(bool includeZeros) {
}
void Stats::endOfInit() {
int orig_names = names->size();
for (int orig_id = 0; orig_id < orig_names; orig_id++) {
int init_id = getStatId("_init_" + (*names)[orig_id]);
log(init_id, (*counts)[orig_id]);
std::unordered_map<uint64_t*, std::string> names_copy(names->begin(), names->end());
for (const auto& p : names_copy) {
uint64_t* init_id = getStatCounter("_init_" + p.second);
log(init_id, *p.first);
}
};
......
......@@ -33,11 +33,11 @@ namespace pyston {
#if STAT_TIMERS
#define STAT_TIMER(id, name) \
static int _stid##id = Stats::getStatId(name); \
StatTimer _st##id(_stid##id)
static uint64_t* _stcounter##id = Stats::getStatCounter(name); \
StatTimer _st##id(_stcounter##id)
#define STAT_TIMER2(id, name, at_time) \
static int _stid##id = Stats::getStatId(name); \
StatTimer _st##id(_stid##id, at_time)
static uint64_t* _stcounter##id = Stats::getStatCounter(name); \
StatTimer _st##id(_stcounter##id, at_time)
#else
#define STAT_TIMER(id, name) StatTimer _st##id(0);
#define STAT_TIMER2(id, name, at_time) StatTimer _st##id(0);
......@@ -48,8 +48,7 @@ namespace pyston {
#if !DISABLE_STATS
struct Stats {
private:
static std::vector<uint64_t>* counts;
static std::unordered_map<int, std::string>* names;
static std::unordered_map<uint64_t*, std::string>* names;
static bool enabled;
static timespec start_ts;
......@@ -59,35 +58,34 @@ public:
static void startEstimatingCPUFreq();
static double estimateCPUFreq();
static int getStatId(const std::string& name);
static std::string getStatName(int id);
static uint64_t* getStatCounter(const std::string& name);
static void setEnabled(bool enabled) { Stats::enabled = enabled; }
static void log(int id, uint64_t count = 1) { (*counts)[id] += count; }
static void log(uint64_t* counter, uint64_t count = 1) { *counter += count; }
static void clear() { std::fill(counts->begin(), counts->end(), 0); }
static void clear();
static void dump(bool includeZeros = true);
static void endOfInit();
};
struct StatCounter {
private:
int id;
uint64_t* counter;
public:
StatCounter(const std::string& name);
void log(uint64_t count = 1) { Stats::log(id, count); }
void log(uint64_t count = 1) { *counter += count; }
};
struct StatPerThreadCounter {
private:
int id = 0;
uint64_t* counter = 0;
public:
StatPerThreadCounter(const std::string& name);
void log(uint64_t count = 1) { Stats::log(id, count); }
void log(uint64_t count = 1) { *counter += count; }
};
#else
......@@ -123,13 +121,13 @@ private:
StatTimer* _prev;
int _statid;
uint64_t* _statcounter;
public:
StatTimer(int statid, bool push = true) {
StatTimer(uint64_t* counter, bool push = true) {
uint64_t at_time = getCPUTicks();
_start_time = 0;
_statid = statid;
_statcounter = counter;
if (!push) {
_prev = NULL;
......@@ -144,9 +142,9 @@ public:
resume(at_time);
}
StatTimer(int statid, uint64_t at_time) {
StatTimer(uint64_t* counter, uint64_t at_time) {
_start_time = 0;
_statid = statid;
_statcounter = counter;
_prev = stack;
stack = this;
if (_prev) {
......@@ -178,7 +176,7 @@ public:
assert(at_time > _start_time);
uint64_t _duration = at_time - _start_time;
Stats::log(_statid, _duration);
Stats::log(_statcounter, _duration);
_start_time = 0;
_last_pause_time = at_time;
......@@ -191,7 +189,6 @@ public:
}
bool isPaused() const { return _start_time == 0; }
int getId() const { return _statid; }
static StatTimer* getStack() { return stack; }
......
......@@ -32,7 +32,7 @@ namespace pyston {
namespace gc {
#if STAT_TIMERS
int gc_alloc_stattimer_id = Stats::getStatId("us_timer_gc_alloc");
uint64_t* gc_alloc_stattimer_counter = Stats::getStatCounter("us_timer_gc_alloc");
#endif
extern "C" void* gc_compat_malloc(size_t sz) noexcept {
......
......@@ -41,11 +41,11 @@ static StatCounter gc_alloc_bytes_typed[] = {
#endif
#if STAT_TIMERS
extern int gc_alloc_stattimer_id;
extern uint64_t* gc_alloc_stattimer_counter;
#endif
extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) {
#if STAT_TIMERS
StatTimer gc_alloc_stattimer(gc_alloc_stattimer_id);
StatTimer gc_alloc_stattimer(gc_alloc_stattimer_counter);
#endif
size_t alloc_bytes = bytes + sizeof(GCAllocation);
......
......@@ -124,13 +124,13 @@ static Box* (*callattrInternal3)(Box*, llvm::StringRef, LookupScope, CallRewrite
= (Box * (*)(Box*, llvm::StringRef, LookupScope, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*))callattrInternal;
#if STAT_TIMERS
static int pyhasher_timer_id = Stats::getStatId("us_timer_PyHasher");
static int pyeq_timer_id = Stats::getStatId("us_timer_PyEq");
static int pylt_timer_id = Stats::getStatId("us_timer_PyLt");
static uint64_t* pyhasher_timer_counter = Stats::getStatCounter("us_timer_PyHasher");
static uint64_t* pyeq_timer_counter = Stats::getStatCounter("us_timer_PyEq");
static uint64_t* pylt_timer_counter = Stats::getStatCounter("us_timer_PyLt");
#endif
size_t PyHasher::operator()(Box* b) const {
#if STAT_TIMERS
StatTimer _st(pyhasher_timer_id);
StatTimer _st(pyhasher_timer_counter);
#endif
if (b->cls == str_cls) {
StringHash<char> H;
......@@ -143,7 +143,7 @@ size_t PyHasher::operator()(Box* b) const {
bool PyEq::operator()(Box* lhs, Box* rhs) const {
#if STAT_TIMERS
StatTimer _st(pyeq_timer_id);
StatTimer _st(pyeq_timer_counter);
#endif
int r = PyObject_RichCompareBool(lhs, rhs, Py_EQ);
......@@ -154,7 +154,7 @@ bool PyEq::operator()(Box* lhs, Box* rhs) const {
bool PyLt::operator()(Box* lhs, Box* rhs) const {
#if STAT_TIMERS
StatTimer _st(pylt_timer_id);
StatTimer _st(pylt_timer_counter);
#endif
int r = PyObject_RichCompareBool(lhs, rhs, Py_LT);
......@@ -1766,8 +1766,8 @@ extern "C" Box* getattr(Box* obj, const char* attr) {
if (VERBOSITY() >= 2) {
#if !DISABLE_STATS
std::string per_name_stat_name = "getattr__" + std::string(attr);
int id = Stats::getStatId(per_name_stat_name);
Stats::log(id);
uint64_t* counter = Stats::getStatCounter(per_name_stat_name);
Stats::log(counter);
#endif
}
......@@ -4834,8 +4834,8 @@ extern "C" Box* getGlobal(Box* globals, const std::string* name) {
if (VERBOSITY() >= 2) {
#if !DISABLE_STATS
std::string per_name_stat_name = "getglobal__" + *name;
int id = Stats::getStatId(per_name_stat_name);
Stats::log(id);
uint64_t* counter = Stats::getStatCounter(per_name_stat_name);
Stats::log(counter);
#endif
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment