Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Improve keep-alive timeout #1102

Merged
merged 1 commit into from
Sep 15, 2016
Merged

Improve keep-alive timeout #1102

merged 1 commit into from
Sep 15, 2016

Conversation

cesarblum
Copy link
Contributor

@cesarblum cesarblum commented Sep 12, 2016

  • Track time more accurately
  • Control timeout in Connection instead of Frame

@halter73 @mikeharder @davidfowl

StopAsync();
}

_secondsSinceLastConnectionEvent++;
Copy link
Contributor

Choose a reason for hiding this comment

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

This relies on Tick() being called exactly once per second, which seems fragile. Have you compared the perf of something like System.Diagnostics.Stopwatch(), which would basically track the precise time of the last connection event, rather than an integer number of seconds?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It hadn't occurred to me to use a Stopwatch to track the time between ticks - I'll try that out. When I first wrote this I did try 3 different ways to track time more accurately but they all had significant perf costs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looking at how Stopwatch is implemented (https://github.com/dotnet/corefx/blob/master/src/System.Runtime.Extensions/src/System/Diagnostics/Stopwatch.cs), I think it'll have the same perf costs as the other stuff I did try before.

Copy link
Contributor

@mikeharder mikeharder Sep 12, 2016

Choose a reason for hiding this comment

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

In this case I would make a few changes:

@cesarblum
Copy link
Contributor Author

cesarblum commented Sep 13, 2016

I must have gotten it right this time, because there's almost no perf impact with my time tracking changes (494ffde) 😁

Averages of five runs of dev vs this change, difference in numbers is due to noise across runs:

dev: 1130819.484 RPS
this PR: 1121710.11 RPS

@cesarblum
Copy link
Contributor Author

@Tratcher

_frame.Tick();
if (_timeoutEnabled)
{
if (_millisecondsSinceLastConnectionEvent > ServerOptions.Limits.ConnectionTimeout.TotalMilliseconds)
Copy link
Member

Choose a reason for hiding this comment

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

Store this so ms doesn't need to be recalculated. You could also add a second to the configuration since _millisecondsSinceLastConnectionEvent could be up to a second too large.

/// </summary>
/// <remarks>
/// Defaults to 2 minutes. Timeout granularity is in seconds. Sub-second values will be rounded to the next second.
/// </remarks>
public TimeSpan KeepAliveTimeout
public TimeSpan ConnectionTimeout
Copy link
Member

Choose a reason for hiding this comment

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

I would rather keep this a timeout for only time spent between request. Having this timeout trigger because an app takes a long time doing business logic before writing a response or completing seems bad to me (even if it would never kill the connection mid request or response).

@cesarblum cesarblum changed the title Change keep-alive timeout to connection timeout (#1101) Improve keep-alive timeout (#1101) Sep 14, 2016
@cesarblum cesarblum changed the title Improve keep-alive timeout (#1101) Improve keep-alive timeout Sep 14, 2016
void IConnectionControl.SetTimeout(long milliseconds)
{
// Add KestrelThread.HeartbeatMilliseconds extra milliseconds since this can be called right before the next heartbeat.
Interlocked.Exchange(ref _timeoutTimestamp, _lastTimestamp + milliseconds + KestrelThread.HeartbeatMilliseconds);
Copy link
Member

Choose a reason for hiding this comment

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

Can we have a Debug.Assert or something verifying that the _timeoutTimestamp was long.MaxValue previously?

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.

mockLibuv.ReadCallback(socket.InternalGetHandle(), 0, ref ignored);
Assert.False(connection.SocketInput.CheckFinOrThrow());
Connection connection = null;
await context.Thread.PostAsync(_ =>
Copy link
Member

Choose a reason for hiding this comment

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

Why does this need to be changed now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because Connection's ctor calls UvLoopHandle.Now(), so it needs to run in the same thread the loop was created.

Copy link
Member

Choose a reason for hiding this comment

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

Ahhh

@halter73
Copy link
Member

I like this sooo much better. Nice 👍

- Track time more accurately
- Control timeout in Connection instead of Frame
@cesarblum cesarblum force-pushed the cesarbs/connection-timeout branch from 8cd46b3 to 1a273f5 Compare September 15, 2016 03:58
@cesarblum cesarblum merged commit 1a273f5 into dev Sep 15, 2016
@cesarblum cesarblum deleted the cesarbs/connection-timeout branch September 15, 2016 04:16
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants