mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
bug 965348 - control SocketTransportService::Poll tick during spdy idle r=hurley
This commit is contained in:
parent
7fd7d52cb1
commit
f0d11b753b
@ -356,6 +356,11 @@ nsSocketTransportService::PollTimeout()
|
||||
if (r < minR)
|
||||
minR = r;
|
||||
}
|
||||
// nsASocketHandler defines UINT16_MAX as do not timeout
|
||||
if (minR == UINT16_MAX) {
|
||||
SOCKET_LOG(("poll timeout: none\n"));
|
||||
return NS_SOCKET_POLL_TIMEOUT;
|
||||
}
|
||||
SOCKET_LOG(("poll timeout: %lu\n", minR));
|
||||
return PR_SecondsToInterval(minR);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
virtual bool CanReuse() = 0;
|
||||
virtual bool RoomForMoreStreams() = 0;
|
||||
virtual PRIntervalTime IdleTime() = 0;
|
||||
virtual void ReadTimeoutTick(PRIntervalTime now) = 0;
|
||||
virtual uint32_t ReadTimeoutTick(PRIntervalTime now) = 0;
|
||||
virtual void DontReuse() = 0;
|
||||
|
||||
static ASpdySession *NewSpdySession(uint32_t version,
|
||||
|
@ -246,7 +246,7 @@ Http2Session::IdleTime()
|
||||
return PR_IntervalNow() - mLastDataReadEpoch;
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
Http2Session::ReadTimeoutTick(PRIntervalTime now)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
@ -255,24 +255,26 @@ Http2Session::ReadTimeoutTick(PRIntervalTime now)
|
||||
this, PR_IntervalToSeconds(now - mLastReadEpoch)));
|
||||
|
||||
if (!mPingThreshold)
|
||||
return;
|
||||
return UINT32_MAX;
|
||||
|
||||
if ((now - mLastReadEpoch) < mPingThreshold) {
|
||||
// recent activity means ping is not an issue
|
||||
if (mPingSentEpoch)
|
||||
mPingSentEpoch = 0;
|
||||
return;
|
||||
|
||||
return PR_IntervalToSeconds(mPingThreshold) -
|
||||
PR_IntervalToSeconds(now - mLastReadEpoch);
|
||||
}
|
||||
|
||||
if (mPingSentEpoch) {
|
||||
LOG3(("Http2Session::ReadTimeoutTick %p handle outstanding ping\n"));
|
||||
if ((now - mPingSentEpoch) >= gHttpHandler->SpdyPingTimeout()) {
|
||||
LOG3(("Http2Session::ReadTimeoutTick %p Ping Timer Exhaustion\n",
|
||||
this));
|
||||
LOG3(("Http2Session::ReadTimeoutTick %p Ping Timer Exhaustion\n", this));
|
||||
mPingSentEpoch = 0;
|
||||
Close(NS_ERROR_NET_TIMEOUT);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
return;
|
||||
return 1; // run the tick aggressively while ping is outstanding
|
||||
}
|
||||
|
||||
LOG3(("Http2Session::ReadTimeoutTick %p generating ping\n", this));
|
||||
@ -311,6 +313,8 @@ Http2Session::ReadTimeoutTick(PRIntervalTime now)
|
||||
CleanupStream(deleteMe, NS_ERROR_ABORT, CANCEL_ERROR);
|
||||
|
||||
} while (deleteMe);
|
||||
|
||||
return 1; // run the tick aggressively while ping is outstanding
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -45,8 +45,11 @@ public:
|
||||
bool CanReuse() { return !mShouldGoAway && !mClosed; }
|
||||
bool RoomForMoreStreams();
|
||||
|
||||
// When the connection is active this is called every 1 second
|
||||
void ReadTimeoutTick(PRIntervalTime now);
|
||||
// When the connection is active this is called up to once every 1 second
|
||||
// return the interval (in seconds) that the connection next wants to
|
||||
// have this invoked. It might happen sooner depending on the needs of
|
||||
// other connections.
|
||||
uint32_t ReadTimeoutTick(PRIntervalTime now);
|
||||
|
||||
// Idle time represents time since "goodput".. e.g. a data or header frame
|
||||
PRIntervalTime IdleTime();
|
||||
|
@ -207,7 +207,7 @@ SpdySession3::IdleTime()
|
||||
return PR_IntervalNow() - mLastDataReadEpoch;
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
SpdySession3::ReadTimeoutTick(PRIntervalTime now)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
@ -217,13 +217,15 @@ SpdySession3::ReadTimeoutTick(PRIntervalTime now)
|
||||
this, PR_IntervalToSeconds(now - mLastReadEpoch)));
|
||||
|
||||
if (!mPingThreshold)
|
||||
return;
|
||||
return UINT32_MAX;
|
||||
|
||||
if ((now - mLastReadEpoch) < mPingThreshold) {
|
||||
// recent activity means ping is not an issue
|
||||
if (mPingSentEpoch)
|
||||
mPingSentEpoch = 0;
|
||||
return;
|
||||
|
||||
return PR_IntervalToSeconds(mPingThreshold) -
|
||||
PR_IntervalToSeconds(now - mLastReadEpoch);
|
||||
}
|
||||
|
||||
if (mPingSentEpoch) {
|
||||
@ -233,8 +235,9 @@ SpdySession3::ReadTimeoutTick(PRIntervalTime now)
|
||||
this));
|
||||
mPingSentEpoch = 0;
|
||||
Close(NS_ERROR_NET_TIMEOUT);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
return;
|
||||
return 1; // run the tick aggressively while ping is outstanding
|
||||
}
|
||||
|
||||
LOG(("SpdySession3::ReadTimeoutTick %p generating ping 0x%X\n",
|
||||
@ -243,7 +246,7 @@ SpdySession3::ReadTimeoutTick(PRIntervalTime now)
|
||||
if (mNextPingID == 0xffffffff) {
|
||||
LOG(("SpdySession3::ReadTimeoutTick %p cannot form ping - ids exhausted\n",
|
||||
this));
|
||||
return;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
mPingSentEpoch = PR_IntervalNow();
|
||||
@ -287,6 +290,7 @@ SpdySession3::ReadTimeoutTick(PRIntervalTime now)
|
||||
"ping ids exhausted marking goaway\n", this));
|
||||
mShouldGoAway = true;
|
||||
}
|
||||
return 1; // run the tick aggressively while ping is outstanding
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -44,8 +44,11 @@ public:
|
||||
bool CanReuse() { return !mShouldGoAway && !mClosed; }
|
||||
bool RoomForMoreStreams();
|
||||
|
||||
// When the connection is active this is called every 1 second
|
||||
void ReadTimeoutTick(PRIntervalTime now);
|
||||
// When the connection is active this is called up to once every 1 second
|
||||
// return the interval (in seconds) that the connection next wants to
|
||||
// have this invoked. It might happen sooner depending on the needs of
|
||||
// other connections.
|
||||
uint32_t ReadTimeoutTick(PRIntervalTime now);
|
||||
|
||||
// Idle time represents time since "goodput".. e.g. a data or header frame
|
||||
PRIntervalTime IdleTime();
|
||||
|
@ -211,7 +211,7 @@ SpdySession31::IdleTime()
|
||||
return PR_IntervalNow() - mLastDataReadEpoch;
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
SpdySession31::ReadTimeoutTick(PRIntervalTime now)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
@ -221,13 +221,15 @@ SpdySession31::ReadTimeoutTick(PRIntervalTime now)
|
||||
this, PR_IntervalToSeconds(now - mLastReadEpoch)));
|
||||
|
||||
if (!mPingThreshold)
|
||||
return;
|
||||
return UINT32_MAX;
|
||||
|
||||
if ((now - mLastReadEpoch) < mPingThreshold) {
|
||||
// recent activity means ping is not an issue
|
||||
if (mPingSentEpoch)
|
||||
mPingSentEpoch = 0;
|
||||
return;
|
||||
|
||||
return PR_IntervalToSeconds(mPingThreshold) -
|
||||
PR_IntervalToSeconds(now - mLastReadEpoch);
|
||||
}
|
||||
|
||||
if (mPingSentEpoch) {
|
||||
@ -237,8 +239,9 @@ SpdySession31::ReadTimeoutTick(PRIntervalTime now)
|
||||
this));
|
||||
mPingSentEpoch = 0;
|
||||
Close(NS_ERROR_NET_TIMEOUT);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
return;
|
||||
return 1; // run the tick aggressively while ping is outstanding
|
||||
}
|
||||
|
||||
LOG(("SpdySession31::ReadTimeoutTick %p generating ping 0x%X\n",
|
||||
@ -247,7 +250,7 @@ SpdySession31::ReadTimeoutTick(PRIntervalTime now)
|
||||
if (mNextPingID == 0xffffffff) {
|
||||
LOG(("SpdySession31::ReadTimeoutTick %p cannot form ping - ids exhausted\n",
|
||||
this));
|
||||
return;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
mPingSentEpoch = PR_IntervalNow();
|
||||
@ -291,6 +294,7 @@ SpdySession31::ReadTimeoutTick(PRIntervalTime now)
|
||||
"ping ids exhausted marking goaway\n", this));
|
||||
mShouldGoAway = true;
|
||||
}
|
||||
return 1; // run the tick aggressively while ping is outstanding
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -43,8 +43,11 @@ public:
|
||||
bool CanReuse() { return !mShouldGoAway && !mClosed; }
|
||||
bool RoomForMoreStreams();
|
||||
|
||||
// When the connection is active this is called every 1 second
|
||||
void ReadTimeoutTick(PRIntervalTime now);
|
||||
// When the connection is active this is called up to once every 1 second
|
||||
// return the interval (in seconds) that the connection next wants to
|
||||
// have this invoked. It might happen sooner depending on the needs of
|
||||
// other connections.
|
||||
uint32_t ReadTimeoutTick(PRIntervalTime now);
|
||||
|
||||
// Idle time represents time since "goodput".. e.g. a data or header frame
|
||||
PRIntervalTime IdleTime();
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsHttpPipeline.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef DEBUG
|
||||
// defined by the socket transport service while active
|
||||
@ -941,21 +942,22 @@ nsHttpConnection::TakeTransport(nsISocketTransport **aTransport,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
nsHttpConnection::ReadTimeoutTick(PRIntervalTime now)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
// make sure timer didn't tick before Activate()
|
||||
if (!mTransaction)
|
||||
return;
|
||||
return UINT32_MAX;
|
||||
|
||||
// Spdy implements some timeout handling using the SPDY ping frame.
|
||||
if (mSpdySession) {
|
||||
mSpdySession->ReadTimeoutTick(now);
|
||||
return;
|
||||
return mSpdySession->ReadTimeoutTick(now);
|
||||
}
|
||||
|
||||
uint32_t nextTickAfter = UINT32_MAX;
|
||||
|
||||
// Timeout if the response is taking too long to arrive.
|
||||
if (mResponseTimeoutEnabled) {
|
||||
PRIntervalTime initialResponseDelta = now - mLastWriteTime;
|
||||
@ -968,12 +970,15 @@ nsHttpConnection::ReadTimeoutTick(PRIntervalTime now)
|
||||
|
||||
// This will also close the connection
|
||||
CloseTransaction(mTransaction, NS_ERROR_NET_TIMEOUT);
|
||||
return;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
nextTickAfter = PR_IntervalToSeconds(gHttpHandler->ResponseTimeout()) -
|
||||
PR_IntervalToSeconds(initialResponseDelta);
|
||||
nextTickAfter = std::max(nextTickAfter, 1U);
|
||||
}
|
||||
|
||||
if (!gHttpHandler->GetPipelineRescheduleOnTimeout())
|
||||
return;
|
||||
return nextTickAfter;
|
||||
|
||||
PRIntervalTime delta = now - mLastReadTime;
|
||||
|
||||
@ -987,6 +992,11 @@ nsHttpConnection::ReadTimeoutTick(PRIntervalTime now)
|
||||
// be the place to add general read timeout handling if it is desired.
|
||||
|
||||
uint32_t pipelineDepth = mTransaction->PipelineDepth();
|
||||
if (pipelineDepth > 1) {
|
||||
// if we have pipelines outstanding (not just an idle connection)
|
||||
// then get a fairly quick tick
|
||||
nextTickAfter = 1;
|
||||
}
|
||||
|
||||
if (delta >= gHttpHandler->GetPipelineRescheduleTimeout() &&
|
||||
pipelineDepth > 1) {
|
||||
@ -1009,10 +1019,10 @@ nsHttpConnection::ReadTimeoutTick(PRIntervalTime now)
|
||||
}
|
||||
|
||||
if (delta < gHttpHandler->GetPipelineTimeout())
|
||||
return;
|
||||
return nextTickAfter;
|
||||
|
||||
if (pipelineDepth <= 1 && !mTransaction->PipelinePosition())
|
||||
return;
|
||||
return nextTickAfter;
|
||||
|
||||
// nothing has transpired on this pipelined socket for many
|
||||
// seconds. Call that a total stall and close the transaction.
|
||||
@ -1027,6 +1037,7 @@ nsHttpConnection::ReadTimeoutTick(PRIntervalTime now)
|
||||
|
||||
// This will also close the connection
|
||||
CloseTransaction(mTransaction, NS_ERROR_NET_TIMEOUT);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -142,8 +142,11 @@ public:
|
||||
// authoritatively whether UsingSpdy() or not.
|
||||
bool ReportedNPN() { return mReportedSpdy; }
|
||||
|
||||
// When the connection is active this is called every 1 second
|
||||
void ReadTimeoutTick(PRIntervalTime now);
|
||||
// When the connection is active this is called up to once every 1 second
|
||||
// return the interval (in seconds) that the connection next wants to
|
||||
// have this invoked. It might happen sooner depending on the needs of
|
||||
// other connections.
|
||||
uint32_t ReadTimeoutTick(PRIntervalTime now);
|
||||
|
||||
nsAHttpTransaction::Classifier Classification() { return mClassification; }
|
||||
void Classify(nsAHttpTransaction::Classifier newclass)
|
||||
|
@ -66,6 +66,7 @@ nsHttpConnectionMgr::nsHttpConnectionMgr()
|
||||
, mNumHalfOpenConns(0)
|
||||
, mTimeOfNextWakeUp(UINT64_MAX)
|
||||
, mTimeoutTickArmed(false)
|
||||
, mTimeoutTickNext(1)
|
||||
{
|
||||
LOG(("Creating nsHttpConnectionMgr @%x\n", this));
|
||||
}
|
||||
@ -2439,8 +2440,14 @@ nsHttpConnectionMgr::ActivateTimeoutTick()
|
||||
// Upon running the tick will rearm itself if there are active
|
||||
// connections available.
|
||||
|
||||
if (mTimeoutTick && mTimeoutTickArmed)
|
||||
if (mTimeoutTick && mTimeoutTickArmed) {
|
||||
// make sure we get one iteration on a quick tick
|
||||
if (mTimeoutTickNext > 1) {
|
||||
mTimeoutTickNext = 1;
|
||||
mTimeoutTick->SetDelay(1000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mTimeoutTick) {
|
||||
mTimeoutTick = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
@ -2462,10 +2469,16 @@ nsHttpConnectionMgr::TimeoutTick()
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(mTimeoutTick, "no readtimeout tick");
|
||||
|
||||
LOG(("nsHttpConnectionMgr::TimeoutTick active=%d\n",
|
||||
mNumActiveConns));
|
||||
|
||||
LOG(("nsHttpConnectionMgr::TimeoutTick active=%d\n", mNumActiveConns));
|
||||
// The next tick will be between 1 second and 1 hr
|
||||
// Set it to the max value here, and the TimeoutTickCB()s can
|
||||
// reduce it to their local needs.
|
||||
mTimeoutTickNext = 3600; // 1hr
|
||||
mCT.Enumerate(TimeoutTickCB, this);
|
||||
if (mTimeoutTick) {
|
||||
mTimeoutTickNext = std::max(mTimeoutTickNext, 1U);
|
||||
mTimeoutTick->SetDelay(mTimeoutTickNext * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
@ -2480,8 +2493,10 @@ nsHttpConnectionMgr::TimeoutTickCB(const nsACString &key,
|
||||
|
||||
// first call the tick handler for each active connection
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
for (uint32_t index = 0; index < ent->mActiveConns.Length(); ++index)
|
||||
ent->mActiveConns[index]->ReadTimeoutTick(now);
|
||||
for (uint32_t index = 0; index < ent->mActiveConns.Length(); ++index) {
|
||||
uint32_t connNextTimeout = ent->mActiveConns[index]->ReadTimeoutTick(now);
|
||||
self->mTimeoutTickNext = std::min(self->mTimeoutTickNext, connNextTimeout);
|
||||
}
|
||||
|
||||
// now check for any stalled half open sockets
|
||||
if (ent->mHalfOpens.Length()) {
|
||||
@ -2513,7 +2528,9 @@ nsHttpConnectionMgr::TimeoutTickCB(const nsACString &key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ent->mHalfOpens.Length()) {
|
||||
self->mTimeoutTickNext = 1;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
@ -629,6 +629,7 @@ private:
|
||||
// Disabled when there are no active or half open connections.
|
||||
nsCOMPtr<nsITimer> mTimeoutTick;
|
||||
bool mTimeoutTickArmed;
|
||||
uint32_t mTimeoutTickNext;
|
||||
|
||||
//
|
||||
// the connection table
|
||||
|
Loading…
Reference in New Issue
Block a user