Skip to content

event: add a range timer interface#12106

Closed
akonradi wants to merge 3 commits into
envoyproxy:masterfrom
akonradi:range-timer-interface
Closed

event: add a range timer interface#12106
akonradi wants to merge 3 commits into
envoyproxy:masterfrom
akonradi:range-timer-interface

Conversation

@akonradi
Copy link
Copy Markdown
Contributor

Commit Message: Add RangeTimer interface
Additional Description:
Add an interface for timers that can be enabled for some timeout within a range. The actual choice of when the timer should be triggered is not specified by the interface. Possible implementations of the interface include

  • timers that are triggered when a thread is not busy
  • timers that are triggered early/late in response to load

Risk Level: low
Testing: none (interface only)
Docs Changes: none
Release Notes: none

This supersedes #11806
cc @antoniovicente

Add an interface for timers that can be enabled for some timeout within
a range. The actual choice of when the timer should be triggered is
not specified by the interface. Possible implementations of the
interface include

 - timers that are triggered when a thread is not busy
 - timers that are triggered early/late in response to load

Signed-off-by: Alex Konradi <akonradi@google.com>
@akonradi
Copy link
Copy Markdown
Contributor Author

I'm not super-attached to the name "RangeTimer" but it seemed better than everything else I came up with. "ScaledTimer" implies an implementation that the interface doesn't support, and "MinMaxTimer" seemed too verbose.

Signed-off-by: Alex Konradi <akonradi@google.com>
@antoniovicente
Copy link
Copy Markdown
Contributor

API seems fine. 'RangeTimer' is a fine name, a better name may exist but I don't have one to suggest.

I assume that instances of this interface would be created via Event::Dispatcher?

Comment thread include/envoy/event/timer.h Outdated

/**
* An abstract event timer that can be scheduled for a timeout within a range. The actual timeout
* used is left up to individual implementations.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure what you mean by "The actual timeout used is left up to individual implementations."

I would expect that there will be a single real implementation of this interface in Envoy, and a mock implementation.

@akonradi
Copy link
Copy Markdown
Contributor Author

The dispatcher could produce naive implementations that just trigger on the min or max, but that's not my target use case. I want to use these range timers to allow the Overload Manager to produce timers that it can trigger early if necessary. I'm working on an intermediate class similar to the one in #11773 to encapsulate the management logic.

@antoniovicente
Copy link
Copy Markdown
Contributor

The dispatcher could produce naive implementations that just trigger on the min or max, but that's not my target use case. I want to use these range timers to allow the Overload Manager to produce timers that it can trigger early if necessary. I'm working on an intermediate class similar to the one in #11773 to encapsulate the management logic.

RangeTimers created via the dispatcher interface could get feedback from overload manager.

@akonradi
Copy link
Copy Markdown
Contributor Author

The Overload Manager already depends on the main thread dispatcher (and the TLS for worker threads), and it seems like some kind of layering violation for the dispatcher to depend on it as well. Since RangeTimer objects can be implemented using regular Timers, I'd rather build on top of the dispatcher instead of into it.

@antoniovicente
Copy link
Copy Markdown
Contributor

The Overload Manager already depends on the main thread dispatcher (and the TLS for worker threads), and it seems like some kind of layering violation for the dispatcher to depend on it as well. Since RangeTimer objects can be implemented using regular Timers, I'd rather build on top of the dispatcher instead of into it.

Timers do need to be associated with the dispatcher of the thread that owns the relevant connection/request. Overload manager being a single process wide entity makes it unsuitable for timer creation. At the very least the overload manager range timer creation method would need to accept a reference to the current thread dispatcher.

@akonradi
Copy link
Copy Markdown
Contributor Author

My plan is to use the ThreadLocalOverloadState as the owner for the timers. It can be constructed with a reference to the dispatcher and use that to create timers in the worker thread.

Signed-off-by: Alex Konradi <akonradi@google.com>
Copy link
Copy Markdown
Contributor

@antoniovicente antoniovicente left a comment

Choose a reason for hiding this comment

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

My plan is to use the ThreadLocalOverloadState as the owner for the timers. It can be constructed with a reference to the dispatcher and use that to create timers in the worker thread.

You may want to ask others for opinions. My preference continues to be for Event::Dispatcher being the sole source of objects scheduled on the event loop.

Comment thread test/mocks/event/mocks.h
callback_();
return;
}
ScopeTrackerScopeState scope(scope_, *dispatcher_);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You need to accept dispatcher as a constructor argument, otherwise you'll run problems with this line.

Comment thread test/mocks/event/mocks.cc

MockTimer::~MockTimer() = default;

MockRangeTimer::MockRangeTimer() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Were these changes intended to be part of this PR or some future PR?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This one. You mentioned expecting a mock, I assumed it should be included here. I can hold off on this until later though.

@akonradi
Copy link
Copy Markdown
Contributor Author

@htuch Can you weigh in re returning RangeTimers from Event::Dispatcher? Who else should be involved in the discussion?

@htuch
Copy link
Copy Markdown
Member

htuch commented Jul 16, 2020

I guess I'm of the same opinion I was earlier; ideally dispatcher has a minimal interface and provides timing primitives, basically the existing timers. Then we build up more sophisticated things like range timers using these. Given the limited scope of range timers (i.e. just some parts of the data path), it doesn't seem worth cramming in there.

The rationale for this layering in my mind is that by keeping dispatcher a minimal interface, we can easily port it. Whether it's to different operating system or event managers. It's also easier to reason about, e.g. if we want to do scoped accounting across events.

@mattklein123 probably also has some thoughts which may or may not agree with this perspective.

@mattklein123
Copy link
Copy Markdown
Member

@mattklein123 probably also has some thoughts which may or may not agree with this perspective.

I agree with what @htuch wrote. This feels like it could just be a utility layered on top, but it's hard to say until we see its use. Can we potentially just defer this change until there is an actual use case that we can review?

@akonradi
Copy link
Copy Markdown
Contributor Author

Thanks @antoniovicente, @htuch, and @mattklein123 for weighing in. I've sketched out the use case I envision in #11427 (comment)

@antoniovicente
Copy link
Copy Markdown
Contributor

@mattklein123 probably also has some thoughts which may or may not agree with this perspective.

I agree with what @htuch wrote. This feels like it could just be a utility layered on top, but it's hard to say until we see its use. Can we potentially just defer this change until there is an actual use case that we can review?

I honestly don't know what belongs or doesn't belong in the dispatcher interface. I just ran into the Event::Dispatcher::getWatermarkFactory method which added to my confusion. That interface method does predate the introduction of OverloadManager.

I trust your opinions on this matter.

@stale
Copy link
Copy Markdown

stale Bot commented Jul 29, 2020

This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale Bot added the stale stalebot believes this issue/PR has not been touched recently label Jul 29, 2020
@stale
Copy link
Copy Markdown

stale Bot commented Aug 9, 2020

This pull request has been automatically closed because it has not had activity in the last 14 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale Bot closed this Aug 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale stalebot believes this issue/PR has not been touched recently

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants