зеркало из https://github.com/mozilla/gecko-dev.git
Bug 881804 (part 1) - Add support for predictive network actions. r=mcmanus f=honzab sr=biesi
This commit is contained in:
Родитель
09296164ad
Коммит
14a7d1f5a2
|
@ -1374,6 +1374,24 @@ pref("network.dir.format", 2);
|
|||
// enables the prefetch service (i.e., prefetching of <link rel="next"> URLs).
|
||||
pref("network.prefetch-next", true);
|
||||
|
||||
// enables the predictive service
|
||||
pref("network.seer.enabled", true);
|
||||
pref("network.seer.enable-hover-on-ssl", false);
|
||||
pref("network.seer.page-degradation.day", 0);
|
||||
pref("network.seer.page-degradation.week", 5);
|
||||
pref("network.seer.page-degradation.month", 10);
|
||||
pref("network.seer.page-degradation.year", 25);
|
||||
pref("network.seer.page-degradation.max", 50);
|
||||
pref("network.seer.subresource-degradation.day", 1);
|
||||
pref("network.seer.subresource-degradation.week", 10);
|
||||
pref("network.seer.subresource-degradation.month", 25);
|
||||
pref("network.seer.subresource-degradation.year", 50);
|
||||
pref("network.seer.subresource-degradation.max", 100);
|
||||
pref("network.seer.preconnect-min-confidence", 90);
|
||||
pref("network.seer.preresolve-min-confidence", 60);
|
||||
pref("network.seer.redirect-likely-confidence", 75);
|
||||
pref("network.seer.max-queue-size", 50);
|
||||
|
||||
|
||||
// The following prefs pertain to the negotiate-auth extension (see bug 17578),
|
||||
// which provides transparent Kerberos or NTLM authentication using the SPNEGO
|
||||
|
|
|
@ -56,6 +56,8 @@ XPIDL_SOURCES += [
|
|||
'nsINetUtil.idl',
|
||||
'nsINetworkLinkService.idl',
|
||||
'nsINetworkProperties.idl',
|
||||
'nsINetworkSeer.idl',
|
||||
'nsINetworkSeerVerifier.idl',
|
||||
'nsINSSErrorsService.idl',
|
||||
'nsIParentChannel.idl',
|
||||
'nsIParentRedirectingChannel.idl',
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
/* vim: set ts=2 sts=2 et sw=2: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsILoadContext;
|
||||
interface nsINetworkSeerVerifier;
|
||||
|
||||
typedef unsigned long SeerPredictReason;
|
||||
typedef unsigned long SeerLearnReason;
|
||||
|
||||
/**
|
||||
* nsINetworkSeer - learn about pages users visit, and allow us to take
|
||||
* predictive actions upon future visits.
|
||||
* NOTE: nsINetworkSeer should only be used on the main thread
|
||||
*/
|
||||
[scriptable, uuid(884a39a0-a3ed-4855-826a-fabb73ae878d)]
|
||||
interface nsINetworkSeer : nsISupports
|
||||
{
|
||||
/**
|
||||
* Prediction reasons
|
||||
*
|
||||
* PREDICT_LINK - we are being asked to take predictive action because
|
||||
* the user is hovering over a link.
|
||||
*
|
||||
* PREDICT_LOAD - we are being asked to take predictive action because
|
||||
* the user has initiated a pageload.
|
||||
*
|
||||
* PREDICT_STARTUP - we are being asked to take predictive action
|
||||
* because the browser is starting up.
|
||||
*/
|
||||
const SeerPredictReason PREDICT_LINK = 0;
|
||||
const SeerPredictReason PREDICT_LOAD = 1;
|
||||
const SeerPredictReason PREDICT_STARTUP = 2;
|
||||
|
||||
/**
|
||||
* Start taking predictive actions
|
||||
*
|
||||
* Calling this will cause the seer to (possibly) start
|
||||
* taking actions such as DNS prefetch and/or TCP preconnect based on
|
||||
* (1) the host name that we are given, and (2) the reason we are being
|
||||
* asked to take actions.
|
||||
*
|
||||
* @param targetURI - The URI we are being asked to take actions based on.
|
||||
* @param sourceURI - The URI that is currently loaded. This is so we can
|
||||
* avoid doing predictive actions for link hover on an HTTPS page (for
|
||||
* example).
|
||||
* @param reason - The reason we are being asked to take actions. Can be
|
||||
* any of the PREDICT_* values above.
|
||||
* In the case of PREDICT_LINK, targetURI should be the URI of the link
|
||||
* that is being hovered over, and sourceURI should be the URI of the page
|
||||
* on which the link appears.
|
||||
* In the case of PREDICT_LOAD, targetURI should be the URI of the page that
|
||||
* is being loaded and sourceURI should be null.
|
||||
* In the case of PREDICT_STARTUP, both targetURI and sourceURI should be
|
||||
* null.
|
||||
* @param loadContext - The nsILoadContext of the page load we are predicting
|
||||
* about.
|
||||
* @param verifier - An nsINetworkSeerVerifier used in testing to ensure we're
|
||||
* predicting the way we expect to. Not necessary (or desired) for normal
|
||||
* operation.
|
||||
*/
|
||||
void predict(in nsIURI targetURI,
|
||||
in nsIURI sourceURI,
|
||||
in SeerPredictReason reason,
|
||||
in nsILoadContext loadContext,
|
||||
in nsINetworkSeerVerifier verifier);
|
||||
|
||||
|
||||
/*
|
||||
* Reasons we are learning something
|
||||
*
|
||||
* LEARN_LOAD_TOPLEVEL - we are learning about the toplevel resource of a
|
||||
* pageload (NOTE: this should ONLY be used by tests)
|
||||
*
|
||||
* LEARN_LOAD_SUBRESOURCE - we are learning a subresource from a pageload
|
||||
*
|
||||
* LEARN_LOAD_REDIRECT - we are learning about the re-direct of a URI
|
||||
*
|
||||
* LEARN_STARTUP - we are learning about a page loaded during startup
|
||||
*/
|
||||
const SeerLearnReason LEARN_LOAD_TOPLEVEL = 0;
|
||||
const SeerLearnReason LEARN_LOAD_SUBRESOURCE = 1;
|
||||
const SeerLearnReason LEARN_LOAD_REDIRECT = 2;
|
||||
const SeerLearnReason LEARN_STARTUP = 3;
|
||||
|
||||
/**
|
||||
* Add to our compendium of knowledge
|
||||
*
|
||||
* This adds to our prediction database to make things (hopefully)
|
||||
* smarter next time we predict something.
|
||||
*
|
||||
* @param targetURI - The URI that was loaded that we are keeping track of.
|
||||
* @param sourceURI - The URI that caused targetURI to be loaded (for page
|
||||
* loads). This means the DOCUMENT URI.
|
||||
* @param reason - The reason we are learning this bit of knowledge.
|
||||
* Reason can be any of the LEARN_* values.
|
||||
* In the case of LEARN_LOAD_SUBRESOURCE, targetURI should be the URI of a
|
||||
* subresource of a page, and sourceURI should be the top-level URI.
|
||||
* In the case of LEARN_LOAD_REDIRECT, targetURI is the NEW URI of a
|
||||
* top-level resource that was redirected to, and sourceURI is the
|
||||
* ORIGINAL URI of said top-level resource.
|
||||
* In the case of LEARN_STARTUP, targetURI should be the URI of a page
|
||||
* that was loaded immediately after browser startup, and sourceURI should
|
||||
* be null.
|
||||
* @param loadContext - The nsILoadContext for the page load that we are
|
||||
* learning about.
|
||||
*/
|
||||
void learn(in nsIURI targetURI,
|
||||
in nsIURI sourceURI,
|
||||
in SeerLearnReason reason,
|
||||
in nsILoadContext loadContext);
|
||||
|
||||
/**
|
||||
* Clear out all our learned knowledge
|
||||
*
|
||||
* This removes everything from our database so that any predictions begun
|
||||
* after this completes will start from a blank slate.
|
||||
*/
|
||||
void reset();
|
||||
};
|
||||
|
||||
%{C++
|
||||
// Wrapper functions to make use of the seer easier and less invasive
|
||||
class nsIChannel;
|
||||
class nsIDocument;
|
||||
class nsILoadContext;
|
||||
class nsILoadGroup;
|
||||
class nsINetworkSeerVerifier;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
nsresult SeerPredict(nsIURI *targetURI,
|
||||
nsIURI *sourceURI,
|
||||
SeerPredictReason reason,
|
||||
nsILoadContext *loadContext,
|
||||
nsINetworkSeerVerifier *verifier);
|
||||
|
||||
nsresult SeerLearn(nsIURI *targetURI,
|
||||
nsIURI *sourceURI,
|
||||
SeerLearnReason reason,
|
||||
nsILoadContext *loadContext);
|
||||
|
||||
nsresult SeerLearn(nsIURI *targetURI,
|
||||
nsIURI *sourceURI,
|
||||
SeerLearnReason reason,
|
||||
nsILoadGroup *loadGroup);
|
||||
|
||||
nsresult SeerLearn(nsIURI *targetURI,
|
||||
nsIURI *sourceURI,
|
||||
SeerLearnReason reason,
|
||||
nsIDocument *document);
|
||||
|
||||
nsresult SeerLearnRedirect(nsIURI *targetURI,
|
||||
nsIChannel *channel,
|
||||
nsILoadContext *loadContext);
|
||||
|
||||
} // mozilla::net
|
||||
} // mozilla
|
||||
%}
|
|
@ -0,0 +1,31 @@
|
|||
/* vim: set ts=2 sts=2 et sw=2: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* nsINetworkSeerVerifier - used for testing the network seer to ensure it
|
||||
* does what we expect it to do.
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, uuid(ea273653-43a8-4632-8b30-4032e0918e8b)]
|
||||
interface nsINetworkSeerVerifier : nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback for when we do a predictive preconnect
|
||||
*
|
||||
* @param uri - The URI that was preconnected to
|
||||
*/
|
||||
void onPredictPreconnect(in nsIURI uri);
|
||||
|
||||
/**
|
||||
* Callback for when we do a predictive DNS lookup
|
||||
*
|
||||
* @param uri - The URI that was looked up
|
||||
*/
|
||||
void onPredictDNS(in nsIURI uri);
|
||||
};
|
|
@ -30,3 +30,31 @@ interface nsISpeculativeConnect : nsISupports
|
|||
|
||||
};
|
||||
|
||||
/**
|
||||
* This is used to override the default values for various values (documented
|
||||
* inline) to determine whether or not to actually make a speculative
|
||||
* connection.
|
||||
*/
|
||||
[builtinclass, uuid(2b6d6fb6-ab28-4f4c-af84-bfdbb7866d72)]
|
||||
interface nsISpeculativeConnectionOverrider : nsISupports
|
||||
{
|
||||
/**
|
||||
* Used to determine the maximum number of unused speculative connections
|
||||
* we will have open for a host at any one time
|
||||
*/
|
||||
[infallible] readonly attribute unsigned long parallelSpeculativeConnectLimit;
|
||||
|
||||
/**
|
||||
* Used to loosen the restrictions nsHttpConnectionMgr::RestrictConnections
|
||||
* to allow more speculative connections when we're unsure if a host will
|
||||
* connect via SPDY or not.
|
||||
*/
|
||||
[infallible] readonly attribute boolean ignorePossibleSpdyConnections;
|
||||
|
||||
/**
|
||||
* Used to determine if we will ignore the existence of any currently idle
|
||||
* connections when we decide whether or not to make a speculative
|
||||
* connection.
|
||||
*/
|
||||
[infallible] readonly attribute boolean ignoreIdle;
|
||||
};
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,207 @@
|
|||
/* vim: set ts=2 sts=2 et sw=2: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_net_Seer_h
|
||||
#define mozilla_net_Seer_h
|
||||
|
||||
#include "nsINetworkSeer.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsISpeculativeConnect.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/storage/StatementCache.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
class nsIDNSService;
|
||||
class nsINetworkSeerVerifier;
|
||||
class nsIThread;
|
||||
|
||||
class mozIStorageConnection;
|
||||
class mozIStorageService;
|
||||
class mozIStorageStatement;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
typedef nsMainThreadPtrHandle<nsINetworkSeerVerifier> SeerVerifierHandle;
|
||||
|
||||
class SeerPredictionRunner;
|
||||
struct SeerTelemetryAccumulators;
|
||||
class SeerDNSListener;
|
||||
|
||||
class Seer : public nsINetworkSeer
|
||||
, public nsIObserver
|
||||
, public nsISpeculativeConnectionOverrider
|
||||
, public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETWORKSEER
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSISPECULATIVECONNECTIONOVERRIDER
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
Seer();
|
||||
virtual ~Seer();
|
||||
|
||||
nsresult Init();
|
||||
void Shutdown();
|
||||
static nsresult Create(nsISupports *outer, const nsIID& iid, void **result);
|
||||
|
||||
private:
|
||||
friend class SeerPredictionEvent;
|
||||
friend class SeerLearnEvent;
|
||||
friend class SeerResetEvent;
|
||||
friend class SeerPredictionRunner;
|
||||
friend class SeerDBShutdownRunner;
|
||||
|
||||
nsresult EnsureInitStorage();
|
||||
|
||||
// This is a proxy for the information we need from an nsIURI
|
||||
struct UriInfo {
|
||||
nsAutoCString spec;
|
||||
nsAutoCString origin;
|
||||
};
|
||||
|
||||
void PredictForLink(nsIURI *targetURI,
|
||||
nsIURI *sourceURI,
|
||||
nsINetworkSeerVerifier *verifier);
|
||||
void PredictForPageload(const UriInfo &dest,
|
||||
SeerVerifierHandle &verifier,
|
||||
int stackCount,
|
||||
TimeStamp &predictStartTime);
|
||||
void PredictForStartup(SeerVerifierHandle &verifier,
|
||||
TimeStamp &predictStartTime);
|
||||
|
||||
// Whether we're working on a page or an origin
|
||||
enum QueryType {
|
||||
QUERY_PAGE = 0,
|
||||
QUERY_ORIGIN
|
||||
};
|
||||
|
||||
// Holds info from the db about a top-level page or origin
|
||||
struct TopLevelInfo {
|
||||
int32_t id;
|
||||
int32_t loadCount;
|
||||
PRTime lastLoad;
|
||||
};
|
||||
|
||||
// Holds info from the db about a subresource
|
||||
struct SubresourceInfo {
|
||||
int32_t id;
|
||||
int32_t hitCount;
|
||||
PRTime lastHit;
|
||||
};
|
||||
|
||||
nsresult ReserveSpaceInQueue();
|
||||
void FreeSpaceInQueue();
|
||||
|
||||
int CalculateGlobalDegradation(PRTime now,
|
||||
PRTime lastLoad);
|
||||
int CalculateConfidence(int baseConfidence,
|
||||
PRTime lastHit,
|
||||
PRTime lastPossible,
|
||||
int globalDegradation);
|
||||
void SetupPrediction(int confidence,
|
||||
const nsACString &uri,
|
||||
SeerPredictionRunner *runner);
|
||||
|
||||
bool LookupTopLevel(QueryType queryType,
|
||||
const nsACString &key,
|
||||
TopLevelInfo &info);
|
||||
void AddTopLevel(QueryType queryType,
|
||||
const nsACString &key,
|
||||
PRTime now);
|
||||
void UpdateTopLevel(QueryType queryType,
|
||||
const TopLevelInfo &info,
|
||||
PRTime now);
|
||||
bool TryPredict(QueryType queryType,
|
||||
const TopLevelInfo &info,
|
||||
PRTime now,
|
||||
SeerVerifierHandle &verifier,
|
||||
TimeStamp &predictStartTime);
|
||||
bool WouldRedirect(const TopLevelInfo &info,
|
||||
PRTime now,
|
||||
UriInfo &newUri);
|
||||
|
||||
bool LookupSubresource(QueryType queryType,
|
||||
const int32_t parentId,
|
||||
const nsACString &key,
|
||||
SubresourceInfo &info);
|
||||
void AddSubresource(QueryType queryType,
|
||||
const int32_t parentId,
|
||||
const nsACString &key, PRTime now);
|
||||
void UpdateSubresource(QueryType queryType,
|
||||
const SubresourceInfo &info,
|
||||
PRTime now);
|
||||
|
||||
void MaybeLearnForStartup(const UriInfo &uri, const PRTime now);
|
||||
|
||||
void LearnForToplevel(const UriInfo &uri);
|
||||
void LearnForSubresource(const UriInfo &targetURI, const UriInfo &sourceURI);
|
||||
void LearnForRedirect(const UriInfo &targetURI, const UriInfo &sourceURI);
|
||||
void LearnForStartup(const UriInfo &uri);
|
||||
|
||||
void ResetInternal();
|
||||
|
||||
// Observer-related stuff
|
||||
nsresult InstallObserver();
|
||||
void RemoveObserver();
|
||||
|
||||
bool mInitialized;
|
||||
|
||||
bool mEnabled;
|
||||
bool mEnableHoverOnSSL;
|
||||
|
||||
int mPageDegradationDay;
|
||||
int mPageDegradationWeek;
|
||||
int mPageDegradationMonth;
|
||||
int mPageDegradationYear;
|
||||
int mPageDegradationMax;
|
||||
|
||||
int mSubresourceDegradationDay;
|
||||
int mSubresourceDegradationWeek;
|
||||
int mSubresourceDegradationMonth;
|
||||
int mSubresourceDegradationYear;
|
||||
int mSubresourceDegradationMax;
|
||||
|
||||
int mPreconnectMinConfidence;
|
||||
int mPreresolveMinConfidence;
|
||||
int mRedirectLikelyConfidence;
|
||||
|
||||
int32_t mMaxQueueSize;
|
||||
|
||||
nsCOMPtr<nsIThread> mIOThread;
|
||||
|
||||
nsCOMPtr<nsISpeculativeConnect> mSpeculativeService;
|
||||
|
||||
nsCOMPtr<nsIFile> mDBFile;
|
||||
nsCOMPtr<mozIStorageService> mStorageService;
|
||||
nsCOMPtr<mozIStorageConnection> mDB;
|
||||
mozilla::storage::StatementCache<mozIStorageStatement> mStatements;
|
||||
|
||||
PRTime mStartupTime;
|
||||
PRTime mLastStartupTime;
|
||||
int32_t mStartupCount;
|
||||
|
||||
nsCOMPtr<nsIDNSService> mDnsService;
|
||||
|
||||
int32_t mQueueSize;
|
||||
mozilla::Mutex mQueueSizeLock;
|
||||
|
||||
nsAutoPtr<SeerTelemetryAccumulators> mAccumulators;
|
||||
|
||||
nsRefPtr<SeerDNSListener> mDNSListener;
|
||||
};
|
||||
|
||||
} // ::mozilla::net
|
||||
} // ::mozilla
|
||||
|
||||
#endif // mozilla_net_Seer_h
|
|
@ -73,6 +73,7 @@ SOURCES += [
|
|||
'nsURLParsers.cpp',
|
||||
'ProxyAutoConfig.cpp',
|
||||
'RedirectChannelRegistrar.cpp',
|
||||
'Seer.cpp',
|
||||
'StreamingProtocolService.cpp',
|
||||
'Tickler.cpp',
|
||||
]
|
||||
|
|
|
@ -436,6 +436,17 @@
|
|||
{ 0x8d, 0x17, 0xa2, 0x7e, 0x44, 0xa8, 0x39, 0x3e } \
|
||||
}
|
||||
|
||||
// service implementing nsINetworkSeer
|
||||
#define NS_NETWORKSEER_CONTRACTID \
|
||||
"@mozilla.org/network/seer;1"
|
||||
#define NS_NETWORKSEER_CID \
|
||||
{ /* {1C218009-A531-46AD-8351-1E7F45D5A3C4} */ \
|
||||
0x1C218009, \
|
||||
0xA531, \
|
||||
0x46AD, \
|
||||
{ 0x83, 0x51, 0x1E, 0x7F, 0x45, 0xD5, 0xA3, 0xC4 } \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* netwerk/cache/ classes
|
||||
*/
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "nsXULAppAPI.h"
|
||||
#include "nsCategoryCache.h"
|
||||
#include "nsIContentSniffer.h"
|
||||
#include "Seer.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIThreadPool.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
|
@ -810,6 +811,7 @@ NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID);
|
|||
NS_DEFINE_NAMED_CID(NS_SERIALIZATION_HELPER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_REDIRECTCHANNELREGISTRAR_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CACHE_STORAGE_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_NETWORKSEER_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
||||
{ &kNS_IOSERVICE_CID, false, nullptr, nsIOServiceConstructor },
|
||||
|
@ -950,6 +952,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
|||
{ &kNS_SERIALIZATION_HELPER_CID, false, nullptr, nsSerializationHelperConstructor },
|
||||
{ &kNS_REDIRECTCHANNELREGISTRAR_CID, false, nullptr, RedirectChannelRegistrarConstructor },
|
||||
{ &kNS_CACHE_STORAGE_SERVICE_CID, false, nullptr, CacheStorageServiceConstructor },
|
||||
{ &kNS_NETWORKSEER_CID, false, NULL, mozilla::net::Seer::Create },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
|
@ -1093,6 +1096,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
|
|||
{ NS_SERIALIZATION_HELPER_CONTRACTID, &kNS_SERIALIZATION_HELPER_CID },
|
||||
{ NS_REDIRECTCHANNELREGISTRAR_CONTRACTID, &kNS_REDIRECTCHANNELREGISTRAR_CID },
|
||||
{ NS_CACHE_STORAGE_SERVICE_CONTRACTID, &kNS_CACHE_STORAGE_SERVICE_CID },
|
||||
{ NS_NETWORKSEER_CONTRACTID, &kNS_NETWORKSEER_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
|
|
|
@ -318,27 +318,70 @@ nsHttpConnectionMgr::DoShiftReloadConnectionCleanup(nsHttpConnectionInfo *aCI)
|
|||
return rv;
|
||||
}
|
||||
|
||||
class SpeculativeConnectArgs
|
||||
{
|
||||
public:
|
||||
SpeculativeConnectArgs() { mOverridesOK = false; }
|
||||
virtual ~SpeculativeConnectArgs() {}
|
||||
|
||||
// Added manually so we can use nsRefPtr without inheriting from
|
||||
// nsISupports
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void);
|
||||
NS_IMETHOD_(nsrefcnt) Release(void);
|
||||
|
||||
public: // intentional!
|
||||
nsRefPtr<NullHttpTransaction> mTrans;
|
||||
|
||||
bool mOverridesOK;
|
||||
uint32_t mParallelSpeculativeConnectLimit;
|
||||
bool mIgnoreIdle;
|
||||
bool mIgnorePossibleSpdyConnections;
|
||||
|
||||
// As above, added manually so we can use nsRefPtr without inheriting from
|
||||
// nsISupports
|
||||
protected:
|
||||
::mozilla::ThreadSafeAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(SpeculativeConnectArgs)
|
||||
NS_IMPL_RELEASE(SpeculativeConnectArgs)
|
||||
|
||||
nsresult
|
||||
nsHttpConnectionMgr::SpeculativeConnect(nsHttpConnectionInfo *ci,
|
||||
nsIInterfaceRequestor *callbacks,
|
||||
uint32_t caps)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "nsHttpConnectionMgr::SpeculativeConnect called off main thread!");
|
||||
|
||||
LOG(("nsHttpConnectionMgr::SpeculativeConnect [ci=%s]\n",
|
||||
ci->HashKey().get()));
|
||||
|
||||
nsRefPtr<SpeculativeConnectArgs> args = new SpeculativeConnectArgs();
|
||||
|
||||
// Wrap up the callbacks and the target to ensure they're released on the target
|
||||
// thread properly.
|
||||
nsCOMPtr<nsIInterfaceRequestor> wrappedCallbacks;
|
||||
NS_NewInterfaceRequestorAggregation(callbacks, nullptr, getter_AddRefs(wrappedCallbacks));
|
||||
|
||||
caps |= ci->GetAnonymous() ? NS_HTTP_LOAD_ANONYMOUS : 0;
|
||||
nsRefPtr<NullHttpTransaction> trans =
|
||||
new NullHttpTransaction(ci, wrappedCallbacks, caps);
|
||||
args->mTrans = new NullHttpTransaction(ci, wrappedCallbacks, caps);
|
||||
|
||||
nsCOMPtr<nsISpeculativeConnectionOverrider> overrider =
|
||||
do_GetInterface(callbacks);
|
||||
if (overrider) {
|
||||
args->mOverridesOK = true;
|
||||
overrider->GetParallelSpeculativeConnectLimit(
|
||||
&args->mParallelSpeculativeConnectLimit);
|
||||
overrider->GetIgnoreIdle(&args->mIgnoreIdle);
|
||||
overrider->GetIgnorePossibleSpdyConnections(
|
||||
&args->mIgnorePossibleSpdyConnections);
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
PostEvent(&nsHttpConnectionMgr::OnMsgSpeculativeConnect, 0, trans);
|
||||
PostEvent(&nsHttpConnectionMgr::OnMsgSpeculativeConnect, 0, args);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
trans.forget();
|
||||
args.forget();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1270,8 @@ nsHttpConnectionMgr::ClosePersistentConnectionsCB(const nsACString &key,
|
|||
}
|
||||
|
||||
bool
|
||||
nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent)
|
||||
nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent,
|
||||
bool ignorePossibleSpdyConnections)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
|
@ -1237,7 +1281,8 @@ nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent)
|
|||
|
||||
bool doRestrict = ent->mConnInfo->UsingSSL() &&
|
||||
gHttpHandler->IsSpdyEnabled() &&
|
||||
(!ent->mTestedSpdy || ent->mUsingSpdy) &&
|
||||
((!ent->mTestedSpdy && !ignorePossibleSpdyConnections) ||
|
||||
ent->mUsingSpdy) &&
|
||||
(ent->mHalfOpens.Length() || ent->mActiveConns.Length());
|
||||
|
||||
// If there are no restrictions, we are done
|
||||
|
@ -1246,7 +1291,7 @@ nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent)
|
|||
|
||||
// If the restriction is based on a tcp handshake in progress
|
||||
// let that connect and then see if it was SPDY or not
|
||||
if (ent->UnconnectedHalfOpens())
|
||||
if (ent->UnconnectedHalfOpens() && !ignorePossibleSpdyConnections)
|
||||
return true;
|
||||
|
||||
// There is a concern that a host is using a mix of HTTP/1 and SPDY.
|
||||
|
@ -2518,14 +2563,14 @@ nsHttpConnectionMgr::OnMsgSpeculativeConnect(int32_t, void *param)
|
|||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
nsRefPtr<NullHttpTransaction> trans =
|
||||
dont_AddRef(static_cast<NullHttpTransaction *>(param));
|
||||
nsRefPtr<SpeculativeConnectArgs> args =
|
||||
dont_AddRef(static_cast<SpeculativeConnectArgs *>(param));
|
||||
|
||||
LOG(("nsHttpConnectionMgr::OnMsgSpeculativeConnect [ci=%s]\n",
|
||||
trans->ConnectionInfo()->HashKey().get()));
|
||||
args->mTrans->ConnectionInfo()->HashKey().get()));
|
||||
|
||||
nsConnectionEntry *ent =
|
||||
GetOrCreateConnectionEntry(trans->ConnectionInfo());
|
||||
GetOrCreateConnectionEntry(args->mTrans->ConnectionInfo());
|
||||
|
||||
// If spdy has previously made a preferred entry for this host via
|
||||
// the ip pooling rules. If so, connect to the preferred host instead of
|
||||
|
@ -2534,10 +2579,22 @@ nsHttpConnectionMgr::OnMsgSpeculativeConnect(int32_t, void *param)
|
|||
if (preferredEntry)
|
||||
ent = preferredEntry;
|
||||
|
||||
if (mNumHalfOpenConns < gHttpHandler->ParallelSpeculativeConnectLimit() &&
|
||||
!ent->mIdleConns.Length() && !RestrictConnections(ent) &&
|
||||
!AtActiveConnectionLimit(ent, trans->Caps())) {
|
||||
CreateTransport(ent, trans, trans->Caps(), true);
|
||||
uint32_t parallelSpeculativeConnectLimit =
|
||||
gHttpHandler->ParallelSpeculativeConnectLimit();
|
||||
bool ignorePossibleSpdyConnections = false;
|
||||
bool ignoreIdle = false;
|
||||
|
||||
if (args->mOverridesOK) {
|
||||
parallelSpeculativeConnectLimit = args->mParallelSpeculativeConnectLimit;
|
||||
ignorePossibleSpdyConnections = args->mIgnorePossibleSpdyConnections;
|
||||
ignoreIdle = args->mIgnoreIdle;
|
||||
}
|
||||
|
||||
if (mNumHalfOpenConns < parallelSpeculativeConnectLimit &&
|
||||
(ignoreIdle || !ent->mIdleConns.Length()) &&
|
||||
!RestrictConnections(ent, ignorePossibleSpdyConnections) &&
|
||||
!AtActiveConnectionLimit(ent, args->mTrans->Caps())) {
|
||||
CreateTransport(ent, args->mTrans, args->mTrans->Caps(), true);
|
||||
}
|
||||
else {
|
||||
LOG((" Transport not created due to existing connection count\n"));
|
||||
|
|
|
@ -512,7 +512,7 @@ private:
|
|||
nsresult BuildPipeline(nsConnectionEntry *,
|
||||
nsAHttpTransaction *,
|
||||
nsHttpPipeline **);
|
||||
bool RestrictConnections(nsConnectionEntry *);
|
||||
bool RestrictConnections(nsConnectionEntry *, bool = false);
|
||||
nsresult ProcessNewTransaction(nsHttpTransaction *);
|
||||
nsresult EnsureSocketThreadTarget();
|
||||
void ClosePersistentConnections(nsConnectionEntry *ent);
|
||||
|
|
|
@ -0,0 +1,295 @@
|
|||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cu = Components.utils;
|
||||
var Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
var seer = null;
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||
var profile = null;
|
||||
|
||||
function extract_origin(uri) {
|
||||
var o = uri.scheme + "://" + uri.asciiHost;
|
||||
if (uri.port !== -1) {
|
||||
o = o + ":" + uri.port;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
var LoadContext = function _loadContext() {
|
||||
};
|
||||
|
||||
LoadContext.prototype = {
|
||||
usePrivateBrowsing: false,
|
||||
|
||||
getInterface: function loadContext_getInterface(iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
QueryInterface: function loadContext_QueryInterface(iid) {
|
||||
if (iid.equals(Ci.nsINetworkSeerVerifier) ||
|
||||
iid.equals(Ci.nsILoadContext)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
|
||||
var load_context = new LoadContext();
|
||||
|
||||
var Verifier = function _verifier(testing, expected_preconnects, expected_preresolves) {
|
||||
this.verifying = testing;
|
||||
this.expected_preconnects = expected_preconnects;
|
||||
this.expected_preresolves = expected_preresolves;
|
||||
};
|
||||
|
||||
Verifier.prototype = {
|
||||
verifying: null,
|
||||
expected_preconnects: null,
|
||||
expected_preresolves: null,
|
||||
|
||||
getInterface: function verifier_getInterface(iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
QueryInterface: function verifier_QueryInterface(iid) {
|
||||
if (iid.equals(Ci.nsINetworkSeerVerifier) ||
|
||||
iid.equals(Ci.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
maybe_run_next_test: function verifier_maybe_run_next_test() {
|
||||
if (this.expected_preconnects.length === 0 &&
|
||||
this.expected_preresolves.length === 0) {
|
||||
do_check_true(true, "Well this is unexpected...");
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
|
||||
onPredictPreconnect: function verifier_onPredictPreconnect(uri) {
|
||||
var origin = extract_origin(uri);
|
||||
var index = this.expected_preconnects.indexOf(origin);
|
||||
if (index == -1) {
|
||||
do_check_true(false, "Got preconnect for unexpected uri " + origin);
|
||||
} else {
|
||||
this.expected_preconnects.splice(index, 1);
|
||||
}
|
||||
this.maybe_run_next_test();
|
||||
},
|
||||
|
||||
onPredictDNS: function verifier_onPredictDNS(uri) {
|
||||
var origin = extract_origin(uri);
|
||||
var index = this.expected_preresolves.indexOf(origin);
|
||||
if (index == -1) {
|
||||
do_check_true(false, "Got preresolve for unexpected uri " + origin);
|
||||
} else {
|
||||
this.expected_preresolves.splice(index, 1);
|
||||
}
|
||||
this.maybe_run_next_test();
|
||||
}
|
||||
};
|
||||
|
||||
function reset_seer() {
|
||||
seer.reset();
|
||||
}
|
||||
|
||||
function newURI(s) {
|
||||
return ios.newURI(s, null, null);
|
||||
}
|
||||
|
||||
function test_link_hover() {
|
||||
reset_seer();
|
||||
var uri = newURI("http://localhost:4444/foo/bar");
|
||||
var referrer = newURI("http://localhost:4444/foo");
|
||||
var preconns = ["http://localhost:4444"];
|
||||
|
||||
var verifier = new Verifier("hover", preconns, []);
|
||||
seer.predict(uri, referrer, seer.PREDICT_LINK, load_context, verifier);
|
||||
}
|
||||
|
||||
function test_pageload() {
|
||||
reset_seer();
|
||||
var toplevel = "http://localhost:4444/index.html";
|
||||
var subresources = [
|
||||
"http://localhost:4444/style.css",
|
||||
"http://localhost:4443/jquery.js",
|
||||
"http://localhost:4444/image.png"
|
||||
];
|
||||
|
||||
var tluri = newURI(toplevel);
|
||||
seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
var preconns = [];
|
||||
for (var i = 0; i < subresources.length; i++) {
|
||||
var sruri = newURI(subresources[i]);
|
||||
seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
preconns.push(extract_origin(sruri));
|
||||
}
|
||||
|
||||
var verifier = new Verifier("pageload", preconns, []);
|
||||
seer.predict(tluri, null, seer.PREDICT_LOAD, load_context, verifier);
|
||||
}
|
||||
|
||||
function test_redirect() {
|
||||
reset_seer();
|
||||
var initial = "http://localhost:4443/redirect";
|
||||
var target = "http://localhost:4444/index.html";
|
||||
var subresources = [
|
||||
"http://localhost:4444/style.css",
|
||||
"http://localhost:4443/jquery.js",
|
||||
"http://localhost:4444/image.png"
|
||||
];
|
||||
|
||||
var inituri = newURI(initial);
|
||||
var targeturi = newURI(target);
|
||||
seer.learn(inituri, null, seer.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
seer.learn(targeturi, inituri, seer.LEARN_LOAD_REDIRECT, load_context);
|
||||
seer.learn(targeturi, null, seer.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
|
||||
var preconns = [];
|
||||
preconns.push(extract_origin(targeturi));
|
||||
for (var i = 0; i < subresources.length; i++) {
|
||||
var sruri = newURI(subresources[i]);
|
||||
seer.learn(sruri, targeturi, seer.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
preconns.push(extract_origin(sruri));
|
||||
}
|
||||
|
||||
var verifier = new Verifier("redirect", preconns, []);
|
||||
seer.predict(inituri, null, seer.PREDICT_LOAD, load_context, verifier);
|
||||
}
|
||||
|
||||
function test_startup() {
|
||||
reset_seer();
|
||||
var uris = [
|
||||
"http://localhost:4444/startup",
|
||||
"http://localhost:4443/startup"
|
||||
];
|
||||
var preconns = [];
|
||||
for (var i = 0; i < uris.length; i++) {
|
||||
var uri = newURI(uris[i]);
|
||||
seer.learn(uri, null, seer.LEARN_STARTUP, load_context);
|
||||
preconns.push(extract_origin(uri));
|
||||
}
|
||||
|
||||
var verifier = new Verifier("startup", preconns, []);
|
||||
seer.predict(null, null, seer.PREDICT_STARTUP, load_context, verifier);
|
||||
}
|
||||
|
||||
// A class used to guarantee serialization of SQL queries so we can properly
|
||||
// update last hit times on subresources to ensure the seer tries to do DNS
|
||||
// preresolve on them instead of preconnecting
|
||||
var DnsContinueVerifier = function _dnsContinueVerifier(subresource, tluri, preresolves) {
|
||||
this.subresource = subresource;
|
||||
this.tluri = tluri;
|
||||
this.preresolves = preresolves;
|
||||
};
|
||||
|
||||
DnsContinueVerifier.prototype = {
|
||||
subresource: null,
|
||||
tluri: null,
|
||||
preresolves: null,
|
||||
|
||||
getInterface: function _dnsContinueVerifier_getInterface(iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
QueryInterface: function _dnsContinueVerifier_QueryInterface(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsINetworkSeerVerifier)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
onPredictPreconnect: function _dnsContinueVerifier_onPredictPreconnect() {
|
||||
// This means that the seer has learned and done our "checkpoint" prediction
|
||||
// Now we can get on with the prediction we actually want to test
|
||||
|
||||
// tstamp is 10 days older than now - just over 1 week, which will ensure we
|
||||
// hit our cutoff for dns vs. preconnect. This is all in usec, hence the
|
||||
// x1000 on the Date object value.
|
||||
var tstamp = (new Date().valueOf() * 1000) - (10 * 86400 * 1000000);
|
||||
|
||||
var dbfile = FileUtils.getFile("ProfD", ["seer.sqlite"]);
|
||||
var dbconn = Services.storage.openDatabase(dbfile);
|
||||
// We also need to update hits, since the toplevel has been "loaded" a
|
||||
// second time (from the prediction that kicked off this callback) to ensure
|
||||
// that the seer will try to do anything for this subresource.
|
||||
var stmt = "UPDATE moz_subresources SET last_hit = " + tstamp + ", hits = 2 WHERE uri = '" + this.subresource + "';";
|
||||
dbconn.executeSimpleSQL(stmt);
|
||||
dbconn.close();
|
||||
|
||||
var verifier = new Verifier("dns", [], this.preresolves);
|
||||
seer.predict(this.tluri, null, seer.PREDICT_LOAD, load_context, verifier);
|
||||
},
|
||||
|
||||
onPredictDNS: function _dnsContinueVerifier_onPredictDNS() {
|
||||
do_check_true(false, "Shouldn't have gotten a preresolve prediction here!");
|
||||
}
|
||||
};
|
||||
|
||||
function test_dns() {
|
||||
reset_seer();
|
||||
var toplevel = "http://localhost:4444/index.html";
|
||||
var subresource = "http://localhost:4443/jquery.js";
|
||||
|
||||
var tluri = newURI(toplevel);
|
||||
seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
var sruri = newURI(subresource);
|
||||
seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
|
||||
var preresolves = [extract_origin(sruri)];
|
||||
var continue_verifier = new DnsContinueVerifier(subresource, tluri, preresolves);
|
||||
// Fire off a prediction that will do preconnects so we know when the seer
|
||||
// thread has gotten to the point where we can update the database manually
|
||||
seer.predict(tluri, null, seer.PREDICT_LOAD, load_context, continue_verifier);
|
||||
}
|
||||
|
||||
function test_origin() {
|
||||
reset_seer();
|
||||
var toplevel = "http://localhost:4444/index.html";
|
||||
var subresources = [
|
||||
"http://localhost:4444/style.css",
|
||||
"http://localhost:4443/jquery.js",
|
||||
"http://localhost:4444/image.png"
|
||||
];
|
||||
|
||||
var tluri = newURI(toplevel);
|
||||
seer.learn(tluri, null, seer.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
var preconns = [];
|
||||
for (var i = 0; i < subresources.length; i++) {
|
||||
var sruri = newURI(subresources[i]);
|
||||
seer.learn(sruri, tluri, seer.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
var origin = extract_origin(sruri);
|
||||
if (preconns.indexOf(origin) === -1) {
|
||||
preconns.push(origin);
|
||||
}
|
||||
}
|
||||
|
||||
var loaduri = newURI("http://localhost:4444/anotherpage.html");
|
||||
var verifier = new Verifier("origin", preconns, []);
|
||||
seer.predict(loaduri, null, seer.PREDICT_LOAD, load_context, verifier);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
test_link_hover,
|
||||
test_pageload,
|
||||
test_redirect,
|
||||
test_startup,
|
||||
test_dns,
|
||||
test_origin
|
||||
];
|
||||
|
||||
function run_test() {
|
||||
tests.forEach(add_test);
|
||||
profile = do_get_profile();
|
||||
seer = Cc["@mozilla.org/network/seer;1"].getService(Ci.nsINetworkSeer);
|
||||
do_register_cleanup(reset_seer);
|
||||
run_next_test();
|
||||
}
|
|
@ -295,3 +295,8 @@ skip-if = os == "android"
|
|||
[test_addr_in_use_error.js]
|
||||
[test_about_networking.js]
|
||||
[test_ping_aboutnetworking.js]
|
||||
[test_seer.js]
|
||||
# Android version detection w/in gecko does not work right on infra, so we just
|
||||
# disable this test on all android versions, even though it's enabled on 2.3+ in
|
||||
# the wild.
|
||||
skip-if = os == "android"
|
||||
|
|
|
@ -1759,6 +1759,126 @@
|
|||
"extended_statistics_ok": true,
|
||||
"description": "Time for an unsuccessful DNS OS resolution (msec)"
|
||||
},
|
||||
"SEER_PREDICT_ATTEMPTS": {
|
||||
"kind": "exponential",
|
||||
"high": "1000 * 1000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Number of times nsINetworkSeer::Predict is called and attempts to predict"
|
||||
},
|
||||
"SEER_LEARN_ATTEMPTS": {
|
||||
"kind": "exponential",
|
||||
"high": "1000 * 1000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Number of times nsINetworkSeer::Learn is called and attempts to learn"
|
||||
},
|
||||
"SEER_PREDICT_FULL_QUEUE": {
|
||||
"kind": "exponential",
|
||||
"high": "60000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Number of times nsINetworkSeer::Predict doesn't continue because the queue is full"
|
||||
},
|
||||
"SEER_LEARN_FULL_QUEUE": {
|
||||
"kind": "exponential",
|
||||
"high": "60000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Number of times nsINetworkSeer::Learn doesn't continue because the queue is full"
|
||||
},
|
||||
"SEER_PREDICT_WAIT_TIME": {
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
"n_buckets": 10,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Amount of time a predict event waits in the queue (ms)"
|
||||
},
|
||||
"SEER_PREDICT_WORK_TIME": {
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
"n_buckets": 10,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Amount of time spent doing the work for predict (ms)"
|
||||
},
|
||||
"SEER_LEARN_WAIT_TIME": {
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
"n_buckets": 10,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Amount of time a learn event waits in the queue (ms)"
|
||||
},
|
||||
"SEER_LEARN_WORK_TIME": {
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
"n_buckets": 10,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Amount of time spent doing the work for learn (ms)"
|
||||
},
|
||||
"SEER_TOTAL_PREDICTIONS": {
|
||||
"kind": "exponential",
|
||||
"high": "1000 * 1000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "How many actual predictions (preresolves, preconnects, ...) happen"
|
||||
},
|
||||
"SEER_TOTAL_PRECONNECTS": {
|
||||
"kind": "exponential",
|
||||
"high": "1000 * 1000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "How many actual preconnects happen"
|
||||
},
|
||||
"SEER_TOTAL_PRERESOLVES": {
|
||||
"kind": "exponential",
|
||||
"high": "1000 * 1000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "How many actual preresolves happen"
|
||||
},
|
||||
"SEER_PREDICTIONS_CALCULATED": {
|
||||
"kind": "exponential",
|
||||
"high": "1000 * 1000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "How many prediction calculations are performed"
|
||||
},
|
||||
"SEER_GLOBAL_DEGRADATION": {
|
||||
"kind": "linear",
|
||||
"high": "100",
|
||||
"n_buckets": 50,
|
||||
"description": "The global degradation calculated"
|
||||
},
|
||||
"SEER_SUBRESOURCE_DEGRADATION": {
|
||||
"kind": "linear",
|
||||
"high": "100",
|
||||
"n_buckets": 50,
|
||||
"description": "The degradation calculated for a subresource"
|
||||
},
|
||||
"SEER_BASE_CONFIDENCE": {
|
||||
"kind": "linear",
|
||||
"high": "100",
|
||||
"n_buckets": 50,
|
||||
"description": "The base confidence calculated for a subresource"
|
||||
},
|
||||
"SEER_CONFIDENCE": {
|
||||
"kind": "linear",
|
||||
"high": "100",
|
||||
"n_buckets": 50,
|
||||
"description": "The final confidence calculated for a subresource"
|
||||
},
|
||||
"SEER_PREDICT_TIME_TO_ACTION": {
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
"n_buckets": 10,
|
||||
"description": "How long it takes from the time Predict() is called to the time we take action"
|
||||
},
|
||||
"SEER_PREDICT_TIME_TO_INACTION": {
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
"n_buckets": 10,
|
||||
"description": "How long it takes from the time Predict() is called to the time we figure out there's nothing to do"
|
||||
},
|
||||
"FIND_PLUGINS": {
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
|
|
Загрузка…
Ссылка в новой задаче