Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

schedule the cycle detector with higher priority using the inject queue #3507

Merged
merged 1 commit into from
Apr 21, 2020

Conversation

sblessing
Copy link
Contributor

@sblessing sblessing commented Apr 19, 2020

This addresses #3501.

PR #2709 introduced the cycle detector being lazily scheduled once a certain amount of cpu ticks (--ponycdinterval) has passed. Scheduler thread 0 would then 'wake up' the the cycle detector by sending it a CHECK_BLOCKED message. The cycle detector would then be appended to back of scheduler-0's queue. The cycle detector would then only be scheduled if either

  1. Scheduler 0 is available (i.e. its queue was empty in the previous loop iteration)
  2. Another scheduler thread is available and steals the cycle detector from scheduler 0's queue. However, this would only happen when the cycle detector has 'travelled' to the head of said queue.

This could create pathological behavior where cycle detection is actually deferred to a point in time where the program would be almost quiescent, especially for programs that create lots of actors right at program start, such that the distance for the cycle detector to reach the head of the scheduling queue might be relatively long.

This change treats the cycle detector as a special system actor that is maintained on the schedulers global inject queue. That is, it is always scheduled using its original start up main context (which is not related to any runtime thread), making sure that a CHECK_BLOCK message (and any other message it would receive after being blocked) will cause it to be pushed to the global inject queue. Every scheduler thread become available would first try to consume an item from this queue before attempting to get an actors from its local queue.

This should have the following effect on runtime system behavior:

  1. Get the cycle detector to be scheduled closer to --ponycdinterval, making this a theoretical upper bound setting
  2. Have the cycle detector to be scheduled with higher priority as it can be 'pop_global'd' by any scheduler thread from the inject queue.
  3. Not defer garbage collection of large actor graphs for long running programs right to the end (or close to) a quiescent system.

@SeanTAllen
Copy link
Member

@sblessing there's a lot of good information about this change in the issue, can you update your commit comment to include a write up of the why for this change? eventually that information will get lost or send someone off having to go look at this issue. I don't want to lose that information and as such want it to be part of the commit comment itself.

@SeanTAllen SeanTAllen requested a review from dipinhora April 19, 2020 12:27
@SeanTAllen SeanTAllen added the changelog - changed Automatically add "Changed" CHANGELOG entry on merge label Apr 19, 2020
@SeanTAllen
Copy link
Member

@sblessing additionally, can you write up a user facing description of this change (the what and why) that a pony user might be interested in so that it can be used in the release notes for this? you can add those release notes as a comment on this PR.

thanks.

Copy link
Contributor

@dipinhora dipinhora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good overall. some minor comments/changes (and a question for the core team). also, as @SeanTAllen mentioned, please update the commit comment with more context about the change so it doesn't get lost (or become hard to find).

once this is merged, i have an idea for how to accomplish the batching i mentioned in the issue.

thanks @sblessing for finding and fixing this unnecessary performance limitation of my changes to the cycle detector stuff (and the detailed issue about it to prompt the discussion and additional thought). and welcome to the (large) group of folks who've found such silliness on my part. 8*P

@@ -86,8 +86,10 @@ static bool well_formed_msg_chain(pony_msg_t* first, pony_msg_t* last)
static void send_unblock(pony_ctx_t* ctx, pony_actor_t* actor)
{
// Send unblock before continuing.
(void)ctx;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, i didn't catch this earlier, but instead of this approach, can you change send_unblock to only take actor as an argument and update the call sites accordingly?


DTRACE2(ACTOR_ALLOC, (uintptr_t)ctx->scheduler, (uintptr_t)actor);
return actor;
}

PONY_API void ponyint_destroy(pony_ctx_t* ctx, pony_actor_t* actor)
{
(void)ctx;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ponylang/core how do you folks feel about changing the signature of ponyint_destroy to remove the ctx argument? (asking because it's marked as PONY_API meaning it's a breaking change)

{
last_cd_tsc = current_tsc;

// cycle detector should now be on the queue
if(actor == NULL)
if(actor == NULL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm assuming this additional trailing space was accidental. if yes, please undo this change.

@@ -1143,7 +1145,9 @@ pony_ctx_t* ponyint_sched_init(uint32_t threads, bool noyield, bool pin,
ponyint_mpmcq_init(&inject);
ponyint_asio_init(asio_cpu);

return pony_ctx();
inject_context = pony_ctx();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add code to ponyint_sched_shutdown to set inject_context = NULL to clean things up.

@sblessing sblessing force-pushed the cycle branch 2 times, most recently from fea2604 to 9f759f2 Compare April 20, 2020 07:54
@sblessing
Copy link
Contributor Author

sblessing commented Apr 20, 2020

I have done the changes requested by @dipinhora. Will amend the commit message and write the user facing documentation later today @SeanTAllen.

@dipinhora please loop me in on the batch processing thoughts. I have some ideas as well and I am also happy to implement those!

…the inject queue (ponylang#3501)

This commit treats the cycle detector as special system actor that is scheduled
using the global inject queue. Consequently, the cycle detector is subject to work
stealing with a higher priority between all scheduler threads. Prior to this change,
the cycle detector was treated like any other application actor. Moreover, scheduler
thread 0 decided when the cycle detector should be activated for it to potentially do
some work. In some cases, this may have caused pathological behavior, where the time
interval --ponycdinterval for 'poking' the cycle detector was theoretically unbounded.

With this commit, the cycle detector always uses the global non-runtime context (inject_context),
whenever messages are sent to it, independent of the sending actor's context. This guarantees
that it will always be pushed to the global inject queue and will then be pop_global'd by the
first runtime thread to become available.

This has the following effect:

a) get the cycle detector to be scheduled closer to --ponycdinterval
b) have the cycle detector to be scheduled with higher priority as it can be 'pop_global'd' by any scheduler thread from the inject queue.
c) not defer garbage collection of large actor graphs for long running programs right to the end (or close to) a quiescent system.
d) locality is not that important for the cycle detector as for application actors, thus scheduling a previously blocked cycle detector
   using a runtime thread on a first-come-first serve basis should have no negative effect on performance.
@sblessing
Copy link
Contributor Author

sblessing commented Apr 20, 2020

user facing documentation and commit message amended @SeanTAllen !

@sblessing sblessing requested a review from dipinhora April 20, 2020 10:43
@SeanTAllen SeanTAllen mentioned this pull request Apr 20, 2020
@SeanTAllen
Copy link
Member

thanks @sblessing. welcome back.

@dipinhora this can be merged once you sign off.

@dipinhora dipinhora merged commit 9032e01 into ponylang:master Apr 21, 2020
github-actions bot pushed a commit that referenced this pull request Apr 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog - changed Automatically add "Changed" CHANGELOG entry on merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants