зеркало из https://github.com/mozilla/pjs.git
bug 729736 - runtime experiment with different spdy ping thresholds r=honzab
This commit is contained in:
Родитель
451c69109e
Коммит
002027aa6c
|
@ -678,6 +678,11 @@ pref("security.fileuri.strict_origin_policy", true);
|
||||||
// prevents necko connecting to ports 1-5 unless the protocol
|
// prevents necko connecting to ports 1-5 unless the protocol
|
||||||
// overrides.
|
// overrides.
|
||||||
|
|
||||||
|
// Allow necko to do A/B testing. Will generally only happen if
|
||||||
|
// telemetry is also enabled as otherwise there is no way to report
|
||||||
|
// the results
|
||||||
|
pref("network.allow-experiments", true);
|
||||||
|
|
||||||
// Default action for unlisted external protocol handlers
|
// Default action for unlisted external protocol handlers
|
||||||
pref("network.protocol-handler.external-default", true); // OK to load
|
pref("network.protocol-handler.external-default", true); // OK to load
|
||||||
pref("network.protocol-handler.warn-external-default", true); // warn before load
|
pref("network.protocol-handler.warn-external-default", true); // warn before load
|
||||||
|
|
|
@ -632,6 +632,9 @@ nsSocketTransportService::Run()
|
||||||
nsCOMPtr<nsIThreadInternal> threadInt = do_QueryInterface(thread);
|
nsCOMPtr<nsIThreadInternal> threadInt = do_QueryInterface(thread);
|
||||||
threadInt->SetObserver(this);
|
threadInt->SetObserver(this);
|
||||||
|
|
||||||
|
// make sure the pseudo random number generator is seeded on this thread
|
||||||
|
srand(PR_Now());
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bool pendingEvents = false;
|
bool pendingEvents = false;
|
||||||
thread->HasPendingEvents(&pendingEvents);
|
thread->HasPendingEvents(&pendingEvents);
|
||||||
|
|
|
@ -93,7 +93,8 @@ SpdySession::SpdySession(nsAHttpTransaction *aHttpTransaction,
|
||||||
mOutputQueueSent(0),
|
mOutputQueueSent(0),
|
||||||
mLastReadEpoch(PR_IntervalNow()),
|
mLastReadEpoch(PR_IntervalNow()),
|
||||||
mPingSentEpoch(0),
|
mPingSentEpoch(0),
|
||||||
mNextPingID(1)
|
mNextPingID(1),
|
||||||
|
mPingThresholdExperiment(false)
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
||||||
|
|
||||||
|
@ -111,6 +112,41 @@ SpdySession::SpdySession(nsAHttpTransaction *aHttpTransaction,
|
||||||
mSendingChunkSize = gHttpHandler->SpdySendingChunkSize();
|
mSendingChunkSize = gHttpHandler->SpdySendingChunkSize();
|
||||||
AddStream(aHttpTransaction, firstPriority);
|
AddStream(aHttpTransaction, firstPriority);
|
||||||
mLastDataReadEpoch = mLastReadEpoch;
|
mLastDataReadEpoch = mLastReadEpoch;
|
||||||
|
|
||||||
|
DeterminePingThreshold();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SpdySession::DeterminePingThreshold()
|
||||||
|
{
|
||||||
|
mPingThreshold = gHttpHandler->SpdyPingThreshold();
|
||||||
|
|
||||||
|
if (!mPingThreshold || !gHttpHandler->AllowExperiments())
|
||||||
|
return;
|
||||||
|
|
||||||
|
PRUint32 randomVal = gHttpHandler->Get32BitsOfPseudoRandom();
|
||||||
|
|
||||||
|
// Use the lower 10 bits to select 1 in 1024 sessions for the
|
||||||
|
// ping threshold experiment. Somewhat less than that will actually be
|
||||||
|
// used because random values greater than the total http idle timeout
|
||||||
|
// for the session are discarded.
|
||||||
|
if ((randomVal & 0x3ff) != 1) // lottery
|
||||||
|
return;
|
||||||
|
|
||||||
|
randomVal = randomVal >> 10; // those bits are used up
|
||||||
|
|
||||||
|
// This session has been selected - use a random ping threshold of 10 +
|
||||||
|
// a random number from 0 to 255, based on the next 8 bits of the
|
||||||
|
// random buffer
|
||||||
|
PRIntervalTime randomThreshold =
|
||||||
|
PR_SecondsToInterval((randomVal & 0xff) + 10);
|
||||||
|
if (randomThreshold > gHttpHandler->IdleTimeout())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mPingThreshold = randomThreshold;
|
||||||
|
mPingThresholdExperiment = true;
|
||||||
|
LOG3(("SpdySession %p Ping Threshold Experimental Selection : %dsec\n",
|
||||||
|
this, PR_IntervalToSeconds(mPingThreshold)));
|
||||||
}
|
}
|
||||||
|
|
||||||
PLDHashOperator
|
PLDHashOperator
|
||||||
|
@ -228,16 +264,16 @@ SpdySession::ReadTimeoutTick(PRIntervalTime now)
|
||||||
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
||||||
NS_ABORT_IF_FALSE(mNextPingID & 1, "Ping Counter Not Odd");
|
NS_ABORT_IF_FALSE(mNextPingID & 1, "Ping Counter Not Odd");
|
||||||
|
|
||||||
PRIntervalTime threshold = gHttpHandler->SpdyPingThreshold();
|
if (!mPingThreshold)
|
||||||
if (!threshold)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LOG(("SpdySession::ReadTimeoutTick %p delta since last read %ds\n",
|
LOG(("SpdySession::ReadTimeoutTick %p delta since last read %ds\n",
|
||||||
this, PR_IntervalToSeconds(now - mLastReadEpoch)));
|
this, PR_IntervalToSeconds(now - mLastReadEpoch)));
|
||||||
|
|
||||||
if ((now - mLastReadEpoch) < threshold) {
|
if ((now - mLastReadEpoch) < mPingThreshold) {
|
||||||
// recent activity means ping is not an issue
|
// recent activity means ping is not an issue
|
||||||
mPingSentEpoch = 0;
|
if (mPingSentEpoch)
|
||||||
|
ClearPing(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,6 +282,7 @@ SpdySession::ReadTimeoutTick(PRIntervalTime now)
|
||||||
if ((now - mPingSentEpoch) >= gHttpHandler->SpdyPingTimeout()) {
|
if ((now - mPingSentEpoch) >= gHttpHandler->SpdyPingTimeout()) {
|
||||||
LOG(("SpdySession::ReadTimeoutTick %p Ping Timer Exhaustion\n",
|
LOG(("SpdySession::ReadTimeoutTick %p Ping Timer Exhaustion\n",
|
||||||
this));
|
this));
|
||||||
|
ClearPing(false);
|
||||||
Close(NS_ERROR_NET_TIMEOUT);
|
Close(NS_ERROR_NET_TIMEOUT);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -273,6 +310,27 @@ SpdySession::ReadTimeoutTick(PRIntervalTime now)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SpdySession::ClearPing(bool pingOK)
|
||||||
|
{
|
||||||
|
mPingSentEpoch = 0;
|
||||||
|
|
||||||
|
if (mPingThresholdExperiment) {
|
||||||
|
LOG3(("SpdySession::ClearPing %p mPingThresholdExperiment %dsec %s\n",
|
||||||
|
this, PR_IntervalToSeconds(mPingThreshold),
|
||||||
|
pingOK ? "pass" :"fail"));
|
||||||
|
|
||||||
|
if (pingOK)
|
||||||
|
Telemetry::Accumulate(Telemetry::SPDY_PING_EXPERIMENT_PASS,
|
||||||
|
PR_IntervalToSeconds(mPingThreshold));
|
||||||
|
else
|
||||||
|
Telemetry::Accumulate(Telemetry::SPDY_PING_EXPERIMENT_FAIL,
|
||||||
|
PR_IntervalToSeconds(mPingThreshold));
|
||||||
|
mPingThreshold = gHttpHandler->SpdyPingThreshold();
|
||||||
|
mPingThresholdExperiment = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PRUint32
|
PRUint32
|
||||||
SpdySession::RegisterStreamID(SpdyStream *stream)
|
SpdySession::RegisterStreamID(SpdyStream *stream)
|
||||||
{
|
{
|
||||||
|
@ -1187,7 +1245,7 @@ SpdySession::HandlePing(SpdySession *self)
|
||||||
|
|
||||||
if (pingID & 0x01) {
|
if (pingID & 0x01) {
|
||||||
// presumably a reply to our timeout ping
|
// presumably a reply to our timeout ping
|
||||||
self->mPingSentEpoch = 0;
|
self->ClearPing(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Servers initiate even numbered pings, go ahead and echo it back
|
// Servers initiate even numbered pings, go ahead and echo it back
|
||||||
|
|
|
@ -188,6 +188,7 @@ private:
|
||||||
PROCESSING_CONTROL_RST_STREAM
|
PROCESSING_CONTROL_RST_STREAM
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void DeterminePingThreshold();
|
||||||
nsresult HandleSynReplyForValidStream();
|
nsresult HandleSynReplyForValidStream();
|
||||||
PRUint32 GetWriteQueueSize();
|
PRUint32 GetWriteQueueSize();
|
||||||
void ChangeDownstreamState(enum stateType);
|
void ChangeDownstreamState(enum stateType);
|
||||||
|
@ -198,6 +199,7 @@ private:
|
||||||
nsresult ConvertHeaders(nsDependentCSubstring &,
|
nsresult ConvertHeaders(nsDependentCSubstring &,
|
||||||
nsDependentCSubstring &);
|
nsDependentCSubstring &);
|
||||||
void GeneratePing(PRUint32);
|
void GeneratePing(PRUint32);
|
||||||
|
void ClearPing(bool);
|
||||||
void GenerateRstStream(PRUint32, PRUint32);
|
void GenerateRstStream(PRUint32, PRUint32);
|
||||||
void GenerateGoAway();
|
void GenerateGoAway();
|
||||||
void CleanupStream(SpdyStream *, nsresult, rstReason);
|
void CleanupStream(SpdyStream *, nsresult, rstReason);
|
||||||
|
@ -345,10 +347,12 @@ private:
|
||||||
PRUint32 mOutputQueueSent;
|
PRUint32 mOutputQueueSent;
|
||||||
nsAutoArrayPtr<char> mOutputQueueBuffer;
|
nsAutoArrayPtr<char> mOutputQueueBuffer;
|
||||||
|
|
||||||
|
PRIntervalTime mPingThreshold;
|
||||||
PRIntervalTime mLastReadEpoch; // used for ping timeouts
|
PRIntervalTime mLastReadEpoch; // used for ping timeouts
|
||||||
PRIntervalTime mLastDataReadEpoch; // used for IdleTime()
|
PRIntervalTime mLastDataReadEpoch; // used for IdleTime()
|
||||||
PRIntervalTime mPingSentEpoch;
|
PRIntervalTime mPingSentEpoch;
|
||||||
PRUint32 mNextPingID;
|
PRUint32 mNextPingID;
|
||||||
|
bool mPingThresholdExperiment;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace mozilla::net
|
}} // namespace mozilla::net
|
||||||
|
|
|
@ -128,6 +128,8 @@ static NS_DEFINE_CID(kSocketProviderServiceCID, NS_SOCKETPROVIDERSERVICE_CID);
|
||||||
#define NETWORK_ENABLEIDN "network.enableIDN"
|
#define NETWORK_ENABLEIDN "network.enableIDN"
|
||||||
#define BROWSER_PREF_PREFIX "browser.cache."
|
#define BROWSER_PREF_PREFIX "browser.cache."
|
||||||
#define DONOTTRACK_HEADER_ENABLED "privacy.donottrackheader.enabled"
|
#define DONOTTRACK_HEADER_ENABLED "privacy.donottrackheader.enabled"
|
||||||
|
#define TELEMETRY_ENABLED "toolkit.telemetry.enabled"
|
||||||
|
#define ALLOW_EXPERIMENTS "network.allow-experiments"
|
||||||
|
|
||||||
#define UA_PREF(_pref) UA_PREF_PREFIX _pref
|
#define UA_PREF(_pref) UA_PREF_PREFIX _pref
|
||||||
#define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
|
#define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
|
||||||
|
@ -200,6 +202,8 @@ nsHttpHandler::nsHttpHandler()
|
||||||
, mSendSecureXSiteReferrer(true)
|
, mSendSecureXSiteReferrer(true)
|
||||||
, mEnablePersistentHttpsCaching(false)
|
, mEnablePersistentHttpsCaching(false)
|
||||||
, mDoNotTrackEnabled(false)
|
, mDoNotTrackEnabled(false)
|
||||||
|
, mTelemetryEnabled(false)
|
||||||
|
, mAllowExperiments(true)
|
||||||
, mEnableSpdy(false)
|
, mEnableSpdy(false)
|
||||||
, mCoalesceSpdy(true)
|
, mCoalesceSpdy(true)
|
||||||
, mUseAlternateProtocol(false)
|
, mUseAlternateProtocol(false)
|
||||||
|
@ -268,6 +272,7 @@ nsHttpHandler::Init()
|
||||||
prefBranch->AddObserver(NETWORK_ENABLEIDN, this, true);
|
prefBranch->AddObserver(NETWORK_ENABLEIDN, this, true);
|
||||||
prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true);
|
prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true);
|
||||||
prefBranch->AddObserver(DONOTTRACK_HEADER_ENABLED, this, true);
|
prefBranch->AddObserver(DONOTTRACK_HEADER_ENABLED, this, true);
|
||||||
|
prefBranch->AddObserver(TELEMETRY_ENABLED, this, true);
|
||||||
|
|
||||||
PrefsChanged(prefBranch, nsnull);
|
PrefsChanged(prefBranch, nsnull);
|
||||||
}
|
}
|
||||||
|
@ -536,6 +541,27 @@ nsHttpHandler::GetIOService(nsIIOService** result)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRUint32
|
||||||
|
nsHttpHandler::Get32BitsOfPseudoRandom()
|
||||||
|
{
|
||||||
|
// only confirm rand seeding on socket thread
|
||||||
|
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
||||||
|
|
||||||
|
// rand() provides different amounts of PRNG on different platforms.
|
||||||
|
// 15 or 31 bits are common amounts.
|
||||||
|
|
||||||
|
PR_STATIC_ASSERT(RAND_MAX >= 0xfff);
|
||||||
|
|
||||||
|
#if RAND_MAX < 0xffffU
|
||||||
|
return ((PRUint16) rand() << 20) |
|
||||||
|
(((PRUint16) rand() & 0xfff) << 8) |
|
||||||
|
((PRUint16) rand() & 0xff);
|
||||||
|
#elif RAND_MAX < 0xffffffffU
|
||||||
|
return ((PRUint16) rand() << 16) | ((PRUint16) rand() & 0xffff);
|
||||||
|
#else
|
||||||
|
return (PRUint32) rand();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHttpHandler::NotifyObservers(nsIHttpChannel *chan, const char *event)
|
nsHttpHandler::NotifyObservers(nsIHttpChannel *chan, const char *event)
|
||||||
|
@ -1187,6 +1213,30 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Telemetry
|
||||||
|
//
|
||||||
|
|
||||||
|
if (PREF_CHANGED(TELEMETRY_ENABLED)) {
|
||||||
|
cVar = false;
|
||||||
|
rv = prefs->GetBoolPref(TELEMETRY_ENABLED, &cVar);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
mTelemetryEnabled = cVar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// network.allow-experiments
|
||||||
|
//
|
||||||
|
|
||||||
|
if (PREF_CHANGED(ALLOW_EXPERIMENTS)) {
|
||||||
|
cVar = true;
|
||||||
|
rv = prefs->GetBoolPref(ALLOW_EXPERIMENTS, &cVar);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
mAllowExperiments = cVar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#undef PREF_CHANGED
|
#undef PREF_CHANGED
|
||||||
#undef MULTI_PREF_CHANGED
|
#undef MULTI_PREF_CHANGED
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,8 @@ public:
|
||||||
PRUint32 MaxSocketCount();
|
PRUint32 MaxSocketCount();
|
||||||
|
|
||||||
bool IsPersistentHttpsCachingEnabled() { return mEnablePersistentHttpsCaching; }
|
bool IsPersistentHttpsCachingEnabled() { return mEnablePersistentHttpsCaching; }
|
||||||
|
bool IsTelemetryEnabled() { return mTelemetryEnabled; }
|
||||||
|
bool AllowExperiments() { return mTelemetryEnabled && mAllowExperiments; }
|
||||||
|
|
||||||
bool IsSpdyEnabled() { return mEnableSpdy; }
|
bool IsSpdyEnabled() { return mEnableSpdy; }
|
||||||
bool CoalesceSpdy() { return mCoalesceSpdy; }
|
bool CoalesceSpdy() { return mCoalesceSpdy; }
|
||||||
|
@ -191,6 +193,9 @@ public:
|
||||||
nsICookieService * GetCookieService(); // not addrefed
|
nsICookieService * GetCookieService(); // not addrefed
|
||||||
nsIStrictTransportSecurityService * GetSTSService();
|
nsIStrictTransportSecurityService * GetSTSService();
|
||||||
|
|
||||||
|
// callable from socket thread only
|
||||||
|
PRUint32 Get32BitsOfPseudoRandom();
|
||||||
|
|
||||||
// Called by the channel before writing a request
|
// Called by the channel before writing a request
|
||||||
void OnModifyRequest(nsIHttpChannel *chan)
|
void OnModifyRequest(nsIHttpChannel *chan)
|
||||||
{
|
{
|
||||||
|
@ -343,6 +348,12 @@ private:
|
||||||
// For broadcasting the preference to not be tracked
|
// For broadcasting the preference to not be tracked
|
||||||
bool mDoNotTrackEnabled;
|
bool mDoNotTrackEnabled;
|
||||||
|
|
||||||
|
// Whether telemetry is reported or not
|
||||||
|
bool mTelemetryEnabled;
|
||||||
|
|
||||||
|
// The value of network.allow-experiments
|
||||||
|
bool mAllowExperiments;
|
||||||
|
|
||||||
// Try to use SPDY features instead of HTTP/1.1 over SSL
|
// Try to use SPDY features instead of HTTP/1.1 over SSL
|
||||||
bool mEnableSpdy;
|
bool mEnableSpdy;
|
||||||
bool mCoalesceSpdy;
|
bool mCoalesceSpdy;
|
||||||
|
|
|
@ -200,6 +200,8 @@ HISTOGRAM(SPDY_SYN_REPLY_RATIO, 1, 99, 20, LINEAR, "SPDY: SYN Reply Header Rati
|
||||||
HISTOGRAM(SPDY_NPN_CONNECT, 0, 1, 2, BOOLEAN, "SPDY: NPN Negotiated")
|
HISTOGRAM(SPDY_NPN_CONNECT, 0, 1, 2, BOOLEAN, "SPDY: NPN Negotiated")
|
||||||
HISTOGRAM(SPDY_NPN_JOIN, 0, 1, 2, BOOLEAN, "SPDY: Coalesce Succeeded")
|
HISTOGRAM(SPDY_NPN_JOIN, 0, 1, 2, BOOLEAN, "SPDY: Coalesce Succeeded")
|
||||||
HISTOGRAM(SPDY_KBREAD_PER_CONN, 1, 3000, 50, EXPONENTIAL, "SPDY: KB read per connection")
|
HISTOGRAM(SPDY_KBREAD_PER_CONN, 1, 3000, 50, EXPONENTIAL, "SPDY: KB read per connection")
|
||||||
|
HISTOGRAM(SPDY_PING_EXPERIMENT_PASS, 10, 355, 64, LINEAR, "SPDY: Ping Interval Passed")
|
||||||
|
HISTOGRAM(SPDY_PING_EXPERIMENT_FAIL, 10, 355, 64, LINEAR, "SPDY: Ping Interval Failed")
|
||||||
|
|
||||||
HISTOGRAM(SPDY_SETTINGS_UL_BW, 1, 10000, 100, EXPONENTIAL, "SPDY: Settings Upload Bandwidth")
|
HISTOGRAM(SPDY_SETTINGS_UL_BW, 1, 10000, 100, EXPONENTIAL, "SPDY: Settings Upload Bandwidth")
|
||||||
HISTOGRAM(SPDY_SETTINGS_DL_BW, 1, 10000, 100, EXPONENTIAL, "SPDY: Settings Download Bandwidth")
|
HISTOGRAM(SPDY_SETTINGS_DL_BW, 1, 10000, 100, EXPONENTIAL, "SPDY: Settings Download Bandwidth")
|
||||||
|
|
Загрузка…
Ссылка в новой задаче