Skip to content

Commit

Permalink
Make cycle detector block checking incremental
Browse files Browse the repository at this point in the history
In PR ponylang#2709, @sylvanc pointed out a concern regarding the cycle
detector creating a message storm due to how it would ask all
actors whether they are blocked or not on every interval.

This commit changes the logic so that the cycle detector only
asks set number of actors whether they are blocked or not. If
it is not able to ask all actors, it will resume iterating actors
on the next iteration.

This commit also addresses @SeanTAllen's concern regarding the
conditional check order using `ponyint_actor_getnoblock`.
  • Loading branch information
dipinhora committed Jun 20, 2018
1 parent ee3f711 commit 7c7cdd8
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
20 changes: 19 additions & 1 deletion src/libponyrt/gc/cycle.c
Expand Up @@ -10,6 +10,8 @@
#include <string.h>
#include <inttypes.h>

#define CD_MAX_CHECK_BLOCKED 1000

typedef struct block_msg_t
{
pony_msg_t msg;
Expand Down Expand Up @@ -137,6 +139,7 @@ typedef struct detector_t

size_t next_token;
size_t detect_interval;
size_t last_checked;

viewmap_t views;
viewmap_t deferred;
Expand Down Expand Up @@ -542,7 +545,7 @@ static void collect(pony_ctx_t* ctx, detector_t* d, perceived_t* per)

static void check_blocked(pony_ctx_t* ctx, detector_t* d)
{
size_t i = HASHMAP_BEGIN;
size_t i = d->last_checked;
view_t* view;

while((view = ponyint_viewmap_next(&d->views, &i)) != NULL)
Expand All @@ -553,8 +556,20 @@ static void check_blocked(pony_ctx_t* ctx, detector_t* d)
{
pony_send(ctx, view->actor, ACTORMSG_ISBLOCKED);
}

// if we've hit the max limit for # of actors to check
if(i > CD_MAX_CHECK_BLOCKED)
break;
}

// if we've reached the end of the map, reset and start from
// the beginning next time else continue from where we left
// off
if(view == NULL)
d->last_checked = HASHMAP_BEGIN;
else
d->last_checked = i;

// process all deferred view stuff
deferred(ctx, d);
}
Expand Down Expand Up @@ -911,6 +926,9 @@ void ponyint_cycle_create(pony_ctx_t* ctx, uint32_t detect_interval)
// 1 second = 2000000000 cycles (approx.)
// based on same scale as ponyint_cpu_core_pause() uses
d->detect_interval = detect_interval * 2000000;

// initialize last_checked
d->last_checked = HASHMAP_BEGIN;
}

bool ponyint_cycle_check_blocked(pony_ctx_t* ctx, uint64_t tsc, uint64_t tsc2)
Expand Down
4 changes: 2 additions & 2 deletions src/libponyrt/sched/scheduler.c
Expand Up @@ -744,7 +744,7 @@ static pony_actor_t* steal(scheduler_t* sched)
}

// if we're scheduler 0 and cycle detection is enabled
if((sched->index == 0) && !ponyint_actor_getnoblock())
if(!ponyint_actor_getnoblock() && (sched->index == 0))
{
// trigger cycle detector by sending it a message if it is time
uint64_t current_tsc = ponyint_cpu_tick();
Expand Down Expand Up @@ -786,7 +786,7 @@ static void run(scheduler_t* sched)
while(true)
{
// if we're scheduler 0 and cycle detection is enabled
if((sched->index == 0) && !ponyint_actor_getnoblock())
if(!ponyint_actor_getnoblock() && (sched->index == 0))
{
// trigger cycle detector by sending it a message if it is time
uint64_t current_tsc = ponyint_cpu_tick();
Expand Down

0 comments on commit 7c7cdd8

Please sign in to comment.