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

dispatcher: Delay fd activation until the next itertion of the event loop. #11750

Merged
merged 3 commits into from
Jun 28, 2020

Conversation

antoniovicente
Copy link
Contributor

Commit Message: dispatcher: Delay fd activation until the next itertion of the event loop.
Additional Description: Processing injected fd events in the same loop they are generated can result in high-throughput connections proxying data multiple times per event loop iteration, effectively starving other connections and increasing small request latency.
Risk Level: high, changes to event loop scheduling behavior and fd event delivery
Testing: unit
Docs Changes: n/a
Release Notes: n/a
Runtime guard: envoy.reloadable_features.activate_fds_next_event_loop

…ted by runtime feature "envoy.reloadable_features.activate_fds_next_event_loop".

Signed-off-by: Antonio Vicente <avd@google.com>
@asraa asraa requested a review from mattklein123 June 25, 2020 16:07
@mattklein123 mattklein123 self-assigned this Jun 25, 2020
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Thanks this is awesome. Just a few small comments.

/wait

// Latched "envoy.reloadable_features.activate_fds_next_event_loop" runtime feature. If true, fd
// events scheduled via activate are evaluated in the next iteration of the event loop after
// polling and activating new fd events.
bool activate_fd_events_next_event_loop_;
Copy link
Member

Choose a reason for hiding this comment

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

nit: const

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Comment on lines +28 to +29
const timeval zero_tv{};
event_add(&raw_event_, &zero_tv);
Copy link
Member

Choose a reason for hiding this comment

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

Can you add some comments here and in scheduleCallbackCurrentIteration about how these libevent invocations differ? It's not completely clear to me and since you have spent so much time looking at libevent source it would be good to leave a comment trail.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added comments.

Originally I read your request as documenting the stages of execution of the event loop. I wasn't sure where a comment like this one would belong:

Rough summary of operations that libevent performs in each event loop iteration, in order:

  1. Calculate the poll timeout by comparing the current time to the deadline of the closest
    timer (the one at head of the priority queue).
  2. Run registered prepare callbacks.
  3. Poll for fd events using the closest timer as timeout, add active fds to the work list.
  4. Run registered "check" callbacks.
  5. Check timer deadlines against current time, add expired timers to the work list.
  6. Execute items in the work list until the list is empty. Note that additional work
    items could be added to the work list during execution of this step.
  7. Goto 1.

Additional work items can be added to the work list so they execute in the current iteration of
the event loop by using one of the mechanisms below. Note that there are no ordering guarantees
when the mixing the mechanisms below.

  • Event::Dispatcher::post(cb), which execute as a group.
  • Event::Dispatcher::deferredDelete(object), which execute as a group together with
    DeferredTaskUtil callbacks.
  • Event::DeferredTaskUtil::deferredRun(dispatcher, cb), which execute as a group together with
    deferredDelete.
  • Event::SchedulableCallback::scheduleCallbackCurrentIteration(), which executes independently.
  • Event::FileEvent::activate() if "envoy.reloadable_features.activate_fds_next_event_loop"
    runtime feature is disabled.
  • Event::Timer::enableTimer(0) if "envoy.reloadable_features.activate_timers_next_event_loop"
    runtime feature is disabled.

Event::FileEvent::activate and Event::SchedulableCallback::scheduleCallbackNextIteration are
implemented as libevent timers with a deadline of 0, so those events are moved to the work list
while checking for expired timers during step 5.

Event execution order, based in the order in which items are added to the work list:
0. Events added via event_active prior to the start of the event loop (in tests)

  1. Fd events
  2. Timers, FileEvent::activate and SchedulableCallback::scheduleCallbackNextIteration
  3. Same iteration work items described above, including Event::Dispatcher::post callbacks

Copy link
Member

Choose a reason for hiding this comment

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

Thanks this is amazing detail. It would be nice to capture this somewhere but up to you where you want to put it.

Perhaps either a small mardown file here: https://github.com/envoyproxy/envoy/tree/master/source/docs
Or here? https://github.com/envoyproxy/envoy/blob/master/source/common/event/libevent_scheduler.h

wdyt? Feel free to do this later as a follow up if you want.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

libevent_scheduler.h seems like a good place for the comment.

I'll add the comment block in the followup PR that introduces "envoy.reloadable_features.activate_timers_next_event_loop"

Signed-off-by: Antonio Vicente <avd@google.com>
@mattklein123
Copy link
Member

CI failure looks legit.

/wait

Signed-off-by: Antonio Vicente <avd@google.com>
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Nice!

@mattklein123 mattklein123 merged commit 9898908 into envoyproxy:master Jun 28, 2020
ggreenway pushed a commit that referenced this pull request Nov 18, 2020
….activate_fds_next_event_loop (#14055)

Feature flag was introduced in PR #11750 on 2020-06-27. Would be good to obsolete in preparation to changes to activate/setEnable behavior which should make activate behavior more intuitive and simplify edge trigger emulation and userspace file event implementations.

Signed-off-by: Antonio Vicente <avd@google.com>
andreyprezotto pushed a commit to andreyprezotto/envoy that referenced this pull request Nov 24, 2020
….activate_fds_next_event_loop (envoyproxy#14055)

Feature flag was introduced in PR envoyproxy#11750 on 2020-06-27. Would be good to obsolete in preparation to changes to activate/setEnable behavior which should make activate behavior more intuitive and simplify edge trigger emulation and userspace file event implementations.

Signed-off-by: Antonio Vicente <avd@google.com>
qqustc pushed a commit to qqustc/envoy that referenced this pull request Nov 24, 2020
….activate_fds_next_event_loop (envoyproxy#14055)

Feature flag was introduced in PR envoyproxy#11750 on 2020-06-27. Would be good to obsolete in preparation to changes to activate/setEnable behavior which should make activate behavior more intuitive and simplify edge trigger emulation and userspace file event implementations.

Signed-off-by: Antonio Vicente <avd@google.com>
Signed-off-by: Qin Qin <qqin@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants