Skip to content

Commit

Permalink
Trigger GC for actors after they process a number of app msgs
Browse files Browse the repository at this point in the history
Prior to this commit, GC would only be triggered if an actor's heap
grew to reach the next heap size cutoff for GC. This would
potentially result in some actors not getting GC'd (and so holding
on to memory for longer than necessary) because they happen to not
allocate large amounts of memory even when processing lots of
application messages and take a very long time to reach the next
heap size for GC to occur.

This commit adds an alternate way that GC for an actor can be
triggered in order to force actors that don't allocate large
amounts of memory to GC and free up memory more frequently. This
is done by keeping track of the number of application messages
processed since the last GC and forcing a GC if the number of
messages handled passes a threshold (10x actor batch size).
  • Loading branch information
dipinhora committed Feb 27, 2019
1 parent 40c748e commit e070b50
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/libponyrt/actor/actor.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#include <valgrind/helgrind.h>
#endif

// number of app messages processed before GC is forced
#define ACTOR_MSGS_TIL_GC 1000

// Ignore padding at the end of the type.
pony_static_assert((offsetof(pony_actor_t, gc) + sizeof(gc_t)) ==
sizeof(pony_actor_pad_t), "Wrong actor pad size!");
Expand Down Expand Up @@ -214,7 +217,10 @@ static bool handle_message(pony_ctx_t* ctx, pony_actor_t* actor,

static void try_gc(pony_ctx_t* ctx, pony_actor_t* actor)
{
if(!ponyint_heap_startgc(&actor->heap))
// only run GC is the heap has grow sufficiently
// or if the actor has processed a sufficient number of application messages
if(!ponyint_heap_startgc(&actor->heap)
&& (actor->msgs_since_gc < ACTOR_MSGS_TIL_GC))
return;

DTRACE1(GC_START, (uintptr_t)ctx->scheduler);
Expand All @@ -227,6 +233,8 @@ static void try_gc(pony_ctx_t* ctx, pony_actor_t* actor)
ponyint_mark_done(ctx);
ponyint_heap_endgc(&actor->heap);

actor->msgs_since_gc = 0;

DTRACE1(GC_END, (uintptr_t)ctx->scheduler);
}

Expand All @@ -251,6 +259,7 @@ bool ponyint_actor_run(pony_ctx_t* ctx, pony_actor_t* actor, size_t batch)
{
// If we handle an application message, try to gc.
app++;
actor->msgs_since_gc++;
try_gc(ctx, actor);

if(app == batch)
Expand All @@ -272,6 +281,7 @@ bool ponyint_actor_run(pony_ctx_t* ctx, pony_actor_t* actor, size_t batch)
{
// If we handle an application message, try to gc.
app++;
actor->msgs_since_gc++;
try_gc(ctx, actor);

// if we become muted as a result of handling a message, bail out now.
Expand Down
1 change: 1 addition & 0 deletions src/libponyrt/actor/actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ typedef struct pony_actor_t
#ifdef USE_ACTOR_CONTINUATIONS
pony_msg_t* continuation;
#endif
uint32_t msgs_since_gc;
PONY_ATOMIC(uint8_t) flags;
PONY_ATOMIC(uint64_t) muted;
PONY_ATOMIC(uint8_t) is_muted;
Expand Down

0 comments on commit e070b50

Please sign in to comment.