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 {
}
};
std::unordered_map<BoxedClass*, TypeStats> by_cls;
TypeStats conservative, untracked;
TypeStats conservative, untracked, hcls;
TypeStats total;
};
......@@ -191,6 +191,9 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
} else if (al->kind_id == GCKind::UNTRACKED) {
stats->untracked.nallocs++;
stats->untracked.nbytes += nbytes;
} else if (al->kind_id == GCKind::HIDDEN_CLASS) {
stats->hcls.nallocs++;
stats->hcls.nbytes += nbytes;
} else {
RELEASE_ASSERT(0, "%d", (int)al->kind_id);
}
......@@ -209,6 +212,7 @@ void Heap::dumpHeapStatistics() {
stats.conservative.print("conservative");
stats.untracked.print("untracked");
stats.hcls.print("hcls");
for (const auto& p : stats.by_cls) {
p.second.print(getFullNameOfClass(p.first).c_str());
}
......
......@@ -17,6 +17,7 @@
#include <algorithm>
#include <cstddef>
#include <cstring>
#include <deque>
#include <sys/mman.h>
#include <ucontext.h>
......@@ -33,7 +34,7 @@
namespace pyston {
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:
#define PAGE_SIZE 4096
......@@ -184,8 +185,13 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
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;
if (available_addrs.size() == 0) {
generator_stack_created.log();
uint64_t stack_low = next_stack_addr;
uint64_t stack_high = stack_low + MAX_STACK_SIZE;
next_stack_addr = stack_high;
......@@ -215,7 +221,11 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
#else
#error "implement me"
#endif
gc::registerGCManagedBytes(MAX_STACK_SIZE);
} else {
generator_stack_reused.log();
#if STACK_GROWS_DOWN
uint64_t stack_high = available_addrs.back();
this->stack_begin = (void*)stack_high;
......@@ -260,9 +270,13 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
v->visitPotentialRange((void**)&g->returnContext,
((void**)&g->returnContext) + sizeof(g->returnContext) / sizeof(void*));
} 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
v->visitPotentialRange((void**)g->context, (void**)g->stack_begin);
v->visitPotentialRange((void**)g->context, (void**)g->stack_begin);
#endif
}
}
}
......@@ -270,8 +284,16 @@ void generatorDestructor(Box* b) {
assert(isSubclass(b->cls, generator_cls));
BoxedGenerator* self = static_cast<BoxedGenerator*>(b);
if (self->stack_begin)
if (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;
}
......
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