Commit 58d587ba authored by Kevin Modzelewski's avatar Kevin Modzelewski

Reduce generators memory usage

Limit the number of generator stacks that we save, and register them as
additional GC pressure.
parent 1a58c87d
...@@ -171,7 +171,7 @@ struct HeapStatistics { ...@@ -171,7 +171,7 @@ struct HeapStatistics {
} }
}; };
std::unordered_map<BoxedClass*, TypeStats> by_cls; std::unordered_map<BoxedClass*, TypeStats> by_cls;
TypeStats conservative, untracked; TypeStats conservative, untracked, hcls;
TypeStats total; TypeStats total;
}; };
...@@ -191,6 +191,9 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) { ...@@ -191,6 +191,9 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
} else if (al->kind_id == GCKind::UNTRACKED) { } else if (al->kind_id == GCKind::UNTRACKED) {
stats->untracked.nallocs++; stats->untracked.nallocs++;
stats->untracked.nbytes += nbytes; stats->untracked.nbytes += nbytes;
} else if (al->kind_id == GCKind::HIDDEN_CLASS) {
stats->hcls.nallocs++;
stats->hcls.nbytes += nbytes;
} else { } else {
RELEASE_ASSERT(0, "%d", (int)al->kind_id); RELEASE_ASSERT(0, "%d", (int)al->kind_id);
} }
...@@ -209,6 +212,7 @@ void Heap::dumpHeapStatistics() { ...@@ -209,6 +212,7 @@ void Heap::dumpHeapStatistics() {
stats.conservative.print("conservative"); stats.conservative.print("conservative");
stats.untracked.print("untracked"); stats.untracked.print("untracked");
stats.hcls.print("hcls");
for (const auto& p : stats.by_cls) { for (const auto& p : stats.by_cls) {
p.second.print(getFullNameOfClass(p.first).c_str()); p.second.print(getFullNameOfClass(p.first).c_str());
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <deque>
#include <sys/mman.h> #include <sys/mman.h>
#include <ucontext.h> #include <ucontext.h>
...@@ -33,7 +34,7 @@ ...@@ -33,7 +34,7 @@
namespace pyston { namespace pyston {
static uint64_t next_stack_addr = 0x3270000000L; static uint64_t next_stack_addr = 0x3270000000L;
static std::vector<uint64_t> available_addrs; static std::deque<uint64_t> available_addrs;
// There should be a better way of getting this: // There should be a better way of getting this:
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
...@@ -184,8 +185,13 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1 ...@@ -184,8 +185,13 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
memcpy(&this->args->elts[0], args, numArgs * sizeof(Box*)); memcpy(&this->args->elts[0], args, numArgs * sizeof(Box*));
} }
static StatCounter generator_stack_reused("generator_stack_reused");
static StatCounter generator_stack_created("generator_stack_created");
void* initial_stack_limit; void* initial_stack_limit;
if (available_addrs.size() == 0) { if (available_addrs.size() == 0) {
generator_stack_created.log();
uint64_t stack_low = next_stack_addr; uint64_t stack_low = next_stack_addr;
uint64_t stack_high = stack_low + MAX_STACK_SIZE; uint64_t stack_high = stack_low + MAX_STACK_SIZE;
next_stack_addr = stack_high; next_stack_addr = stack_high;
...@@ -215,7 +221,11 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1 ...@@ -215,7 +221,11 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
#else #else
#error "implement me" #error "implement me"
#endif #endif
gc::registerGCManagedBytes(MAX_STACK_SIZE);
} else { } else {
generator_stack_reused.log();
#if STACK_GROWS_DOWN #if STACK_GROWS_DOWN
uint64_t stack_high = available_addrs.back(); uint64_t stack_high = available_addrs.back();
this->stack_begin = (void*)stack_high; this->stack_begin = (void*)stack_high;
...@@ -260,18 +270,30 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) { ...@@ -260,18 +270,30 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
v->visitPotentialRange((void**)&g->returnContext, v->visitPotentialRange((void**)&g->returnContext,
((void**)&g->returnContext) + sizeof(g->returnContext) / sizeof(void*)); ((void**)&g->returnContext) + sizeof(g->returnContext) / sizeof(void*));
} else { } else {
// g->context is always set for a running generator, but we can trigger a GC while constructing
// a generator in which case we can see a NULL context
if (g->context) {
#if STACK_GROWS_DOWN #if STACK_GROWS_DOWN
v->visitPotentialRange((void**)g->context, (void**)g->stack_begin); v->visitPotentialRange((void**)g->context, (void**)g->stack_begin);
#endif #endif
} }
}
} }
void generatorDestructor(Box* b) { void generatorDestructor(Box* b) {
assert(isSubclass(b->cls, generator_cls)); assert(isSubclass(b->cls, generator_cls));
BoxedGenerator* self = static_cast<BoxedGenerator*>(b); BoxedGenerator* self = static_cast<BoxedGenerator*>(b);
if (self->stack_begin) if (self->stack_begin) {
available_addrs.push_back((uint64_t)self->stack_begin); available_addrs.push_back((uint64_t)self->stack_begin);
// Limit the number of generator stacks we keep around:
if (available_addrs.size() > 5) {
uint64_t addr = available_addrs.front();
available_addrs.pop_front();
int r = munmap((void*)(addr - MAX_STACK_SIZE), MAX_STACK_SIZE);
assert(r == 0);
}
}
self->stack_begin = NULL; self->stack_begin = NULL;
} }
......
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