mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1009122 - use cache2 as storage for predictor data. r=honzab
--HG-- extra : rebase_source : 290e1aa04a1dfa2e7d6cb9f1b5b705d1ed80e68c
This commit is contained in:
parent
8a22ce4bd0
commit
87facfa179
@ -92,7 +92,7 @@ pref("network.buffer.cache.count", 24);
|
||||
pref("network.buffer.cache.size", 16384);
|
||||
|
||||
// predictive actions
|
||||
pref("network.predictor.enable", false); // disabled on b2g
|
||||
pref("network.predictor.enabled", false); // disabled on b2g
|
||||
pref("network.predictor.max-db-size", 2097152); // bytes
|
||||
pref("network.predictor.preserve", 50); // percentage of predictor data to keep when cleaning up
|
||||
|
||||
|
@ -10174,6 +10174,9 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||
else
|
||||
srcdoc = NullString();
|
||||
|
||||
mozilla::net::PredictorLearn(aURI, nullptr,
|
||||
nsINetworkPredictor::LEARN_LOAD_TOPLEVEL,
|
||||
this);
|
||||
mozilla::net::PredictorPredict(aURI, nullptr,
|
||||
nsINetworkPredictor::PREDICT_LOAD,
|
||||
this, nullptr);
|
||||
|
@ -101,7 +101,7 @@ pref("network.buffer.cache.count", 24);
|
||||
pref("network.buffer.cache.size", 16384);
|
||||
|
||||
// predictive actions
|
||||
pref("network.predictor.enabled", false);
|
||||
pref("network.predictor.enabled", true);
|
||||
pref("network.predictor.max-db-size", 2097152); // bytes
|
||||
pref("network.predictor.preserve", 50); // percentage of predictor data to keep when cleaning up
|
||||
|
||||
|
@ -1584,7 +1584,7 @@ pref("network.dir.format", 2);
|
||||
pref("network.prefetch-next", true);
|
||||
|
||||
// enables the predictive service
|
||||
pref("network.predictor.enabled", false);
|
||||
pref("network.predictor.enabled", true);
|
||||
pref("network.predictor.enable-hover-on-ssl", false);
|
||||
pref("network.predictor.page-degradation.day", 0);
|
||||
pref("network.predictor.page-degradation.week", 5);
|
||||
@ -1599,9 +1599,8 @@ pref("network.predictor.subresource-degradation.max", 100);
|
||||
pref("network.predictor.preconnect-min-confidence", 90);
|
||||
pref("network.predictor.preresolve-min-confidence", 60);
|
||||
pref("network.predictor.redirect-likely-confidence", 75);
|
||||
pref("network.predictor.max-queue-size", 50);
|
||||
pref("network.predictor.max-db-size", 157286400); // bytes
|
||||
pref("network.predictor.preserve", 80); // percentage of predictor data to keep when cleaning up
|
||||
pref("network.predictor.max-resources-per-entry", 100);
|
||||
pref("network.predictor.cleaned-up", false);
|
||||
|
||||
// The following prefs pertain to the negotiate-auth extension (see bug 17578),
|
||||
// which provides transparent Kerberos or NTLM authentication using the SPNEGO
|
||||
|
@ -18,7 +18,7 @@ typedef unsigned long PredictorLearnReason;
|
||||
* NOTE: nsINetworkPredictor should only
|
||||
* be used on the main thread.
|
||||
*/
|
||||
[scriptable, uuid(980f70bc-0487-4b22-a4c1-bf1185c8ae1f)]
|
||||
[scriptable, uuid(acc88e7c-3f39-42c7-ac31-6377c2c3d73e)]
|
||||
interface nsINetworkPredictor : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -122,12 +122,6 @@ interface nsINetworkPredictor : nsISupports
|
||||
* after this completes will start from a blank slate.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* @deprecated THIS API IS FOR TESTING ONLY. IF YOU DON'T KNOW WHAT IT DOES,
|
||||
* DON'T USE IT
|
||||
*/
|
||||
void prepareForDnsTest(in long long timestamp, in string uri);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,36 +9,34 @@
|
||||
#include "nsINetworkPredictor.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICacheEntry.h"
|
||||
#include "nsICacheEntryOpenCallback.h"
|
||||
#include "nsICacheStorageVisitor.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 "nsRefPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
class nsICacheStorage;
|
||||
class nsIDNSService;
|
||||
class nsIIOService;
|
||||
class nsINetworkPredictorVerifier;
|
||||
class nsIThread;
|
||||
class nsITimer;
|
||||
|
||||
class mozIStorageConnection;
|
||||
class mozIStorageService;
|
||||
class mozIStorageStatement;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
typedef nsMainThreadPtrHandle<nsINetworkPredictorVerifier> PredictorVerifierHandle;
|
||||
|
||||
class PredictionRunner;
|
||||
class PredictorDNSListener;
|
||||
|
||||
class Predictor : public nsINetworkPredictor
|
||||
, public nsIObserver
|
||||
, public nsISpeculativeConnectionOverrider
|
||||
, public nsIInterfaceRequestor
|
||||
, public nsICacheEntryMetaDataVisitor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -46,6 +44,7 @@ public:
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSISPECULATIVECONNECTIONOVERRIDER
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICACHEENTRYMETADATAVISITOR
|
||||
|
||||
Predictor();
|
||||
|
||||
@ -56,184 +55,309 @@ public:
|
||||
private:
|
||||
virtual ~Predictor();
|
||||
|
||||
friend class PredictionEvent;
|
||||
friend class LearnEvent;
|
||||
friend class PredictorResetEvent;
|
||||
friend class PredictionRunner;
|
||||
friend class PredictorDBShutdownRunner;
|
||||
friend class PredictorCommitTimerInitEvent;
|
||||
friend class PredictorNewTransactionEvent;
|
||||
friend class PredictorCleanupEvent;
|
||||
|
||||
void CheckForAndDeleteOldDBFile();
|
||||
nsresult EnsureInitStorage();
|
||||
|
||||
// This is a proxy for the information we need from an nsIURI
|
||||
struct UriInfo {
|
||||
nsAutoCString spec;
|
||||
nsAutoCString origin;
|
||||
union Reason {
|
||||
PredictorLearnReason mLearn;
|
||||
PredictorPredictReason mPredict;
|
||||
};
|
||||
|
||||
void PredictForLink(nsIURI *targetURI,
|
||||
nsIURI *sourceURI,
|
||||
nsINetworkPredictorVerifier *verifier);
|
||||
void PredictForPageload(const UriInfo &dest,
|
||||
PredictorVerifierHandle &verifier,
|
||||
int stackCount,
|
||||
TimeStamp &predictStartTime);
|
||||
void PredictForStartup(PredictorVerifierHandle &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,
|
||||
PredictionRunner *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,
|
||||
PredictorVerifierHandle &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,
|
||||
const PRTime now,
|
||||
const int32_t parentCount);
|
||||
|
||||
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();
|
||||
|
||||
void BeginTransaction()
|
||||
class DNSListener : public nsIDNSListener
|
||||
{
|
||||
mDB->BeginTransaction();
|
||||
}
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIDNSLISTENER
|
||||
|
||||
void CommitTransaction()
|
||||
DNSListener()
|
||||
{ }
|
||||
|
||||
private:
|
||||
virtual ~DNSListener()
|
||||
{ }
|
||||
};
|
||||
|
||||
class Action : public nsICacheEntryOpenCallback
|
||||
{
|
||||
mDB->CommitTransaction();
|
||||
}
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHEENTRYOPENCALLBACK
|
||||
|
||||
int64_t GetDBFileSize();
|
||||
int64_t GetDBFileSizeAfterVacuum();
|
||||
void MaybeScheduleCleanup();
|
||||
void Cleanup();
|
||||
void CleanupOrigins(PRTime now);
|
||||
void CleanupStartupPages(PRTime now);
|
||||
int32_t GetSubresourceCount();
|
||||
Action(bool fullUri, bool predict, Reason reason,
|
||||
nsIURI *targetURI, nsIURI *sourceURI,
|
||||
nsINetworkPredictorVerifier *verifier, Predictor *predictor);
|
||||
Action(bool fullUri, bool predict, Reason reason,
|
||||
nsIURI *targetURI, nsIURI *sourceURI,
|
||||
nsINetworkPredictorVerifier *verifier, Predictor *predictor,
|
||||
uint8_t stackCount);
|
||||
|
||||
void VacuumDatabase();
|
||||
static const bool IS_FULL_URI = true;
|
||||
static const bool IS_ORIGIN = false;
|
||||
|
||||
static const bool DO_PREDICT = true;
|
||||
static const bool DO_LEARN = false;
|
||||
|
||||
private:
|
||||
virtual ~Action();
|
||||
|
||||
bool mFullUri : 1;
|
||||
bool mPredict : 1;
|
||||
union {
|
||||
PredictorPredictReason mPredictReason;
|
||||
PredictorLearnReason mLearnReason;
|
||||
};
|
||||
nsCOMPtr<nsIURI> mTargetURI;
|
||||
nsCOMPtr<nsIURI> mSourceURI;
|
||||
nsCOMPtr<nsINetworkPredictorVerifier> mVerifier;
|
||||
TimeStamp mStartTime;
|
||||
uint8_t mStackCount;
|
||||
nsRefPtr<Predictor> mPredictor;
|
||||
};
|
||||
|
||||
class Resetter : public nsICacheEntryOpenCallback,
|
||||
public nsICacheEntryMetaDataVisitor,
|
||||
public nsICacheStorageVisitor
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHEENTRYOPENCALLBACK
|
||||
NS_DECL_NSICACHEENTRYMETADATAVISITOR
|
||||
NS_DECL_NSICACHESTORAGEVISITOR
|
||||
|
||||
explicit Resetter(Predictor *predictor);
|
||||
|
||||
private:
|
||||
virtual ~Resetter() { }
|
||||
|
||||
void Complete();
|
||||
|
||||
uint32_t mEntriesToVisit;
|
||||
nsTArray<nsCString> mKeysToDelete;
|
||||
nsRefPtr<Predictor> mPredictor;
|
||||
nsTArray<nsCOMPtr<nsIURI>> mURIsToVisit;
|
||||
};
|
||||
|
||||
class SpaceCleaner : public nsICacheEntryMetaDataVisitor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICACHEENTRYMETADATAVISITOR
|
||||
|
||||
explicit SpaceCleaner(Predictor *predictor)
|
||||
:mLRUStamp(0)
|
||||
,mKeyToDelete(nullptr)
|
||||
,mPredictor(predictor)
|
||||
{ }
|
||||
|
||||
void Finalize(nsICacheEntry *entry);
|
||||
|
||||
private:
|
||||
virtual ~SpaceCleaner() { }
|
||||
uint32_t mLRUStamp;
|
||||
const char *mKeyToDelete;
|
||||
nsRefPtr<Predictor> mPredictor;
|
||||
};
|
||||
|
||||
// Observer-related stuff
|
||||
nsresult InstallObserver();
|
||||
void RemoveObserver();
|
||||
|
||||
// Service startup utilities
|
||||
void MaybeCleanupOldDBFiles();
|
||||
|
||||
// The guts of prediction
|
||||
|
||||
// This is the top-level driver for doing any prediction that needs
|
||||
// information from the cache. Returns true if any predictions were queued up
|
||||
// * reason - What kind of prediction this is/why this prediction is
|
||||
// happening (pageload, startup)
|
||||
// * entry - the cache entry with the information we need
|
||||
// * isNew - whether or not the cache entry is brand new and empty
|
||||
// * fullUri - whether we are doing predictions based on a full page URI, or
|
||||
// just the origin of the page
|
||||
// * targetURI - the URI that we are predicting based upon - IOW, the URI
|
||||
// that is being loaded or being redirected to
|
||||
// * verifier - used for testing to verify the expected predictions happen
|
||||
// * stackCount - used to ensure we don't recurse too far trying to find the
|
||||
// final redirection in a redirect chain
|
||||
bool PredictInternal(PredictorPredictReason reason, nsICacheEntry *entry,
|
||||
bool isNew, bool fullUri, nsIURI *targetURI,
|
||||
nsINetworkPredictorVerifier *verifier,
|
||||
uint8_t stackCount);
|
||||
|
||||
// Used when predicting because the user's mouse hovered over a link
|
||||
// * targetURI - the URI target of the link
|
||||
// * sourceURI - the URI of the page on which the link appears
|
||||
// * verifier - used for testing to verify the expected predictions happen
|
||||
void PredictForLink(nsIURI *targetURI,
|
||||
nsIURI *sourceURI,
|
||||
nsINetworkPredictorVerifier *verifier);
|
||||
|
||||
// Used when predicting because a page is being loaded (which may include
|
||||
// being the target of a redirect). All arguments are the same as for
|
||||
// PredictInternal. Returns true if any predictions were queued up.
|
||||
bool PredictForPageload(nsICacheEntry *entry,
|
||||
uint8_t stackCount,
|
||||
nsINetworkPredictorVerifier *verifier);
|
||||
|
||||
// Used when predicting pages that will be used near browser startup. All
|
||||
// arguments are the same as for PredictInternal. Returns true if any
|
||||
// predictions were queued up.
|
||||
bool PredictForStartup(nsICacheEntry *entry,
|
||||
nsINetworkPredictorVerifier *verifier);
|
||||
|
||||
// Utilities related to prediction
|
||||
|
||||
// Used to calculate how much to degrade our confidence for all resources
|
||||
// on a particular page, because of how long ago the most recent load of that
|
||||
// page was. Returns a value between 0 (very recent most recent load) and 100
|
||||
// (very distant most recent load)
|
||||
// * lastLoad - time stamp of most recent load of a page
|
||||
int32_t CalculateGlobalDegradation(uint32_t lastLoad);
|
||||
|
||||
// Used to calculate how confident we are that a particular resource will be
|
||||
// used. Returns a value between 0 (no confidence) and 100 (very confident)
|
||||
// * hitCount - number of times this resource has been seen when loading
|
||||
// this page
|
||||
// * hitsPossible - number of times this page has been loaded
|
||||
// * lastHit - timestamp of the last time this resource was seen when
|
||||
// loading this page
|
||||
// * lastPossible - timestamp of the last time this page was loaded
|
||||
// * globalDegradation - value calculated by CalculateGlobalDegradation for
|
||||
// this page
|
||||
int32_t CalculateConfidence(uint32_t hitCount, uint32_t hitsPossible,
|
||||
uint32_t lastHit, uint32_t lastPossible,
|
||||
int32_t globalDegradation);
|
||||
|
||||
// Used to calculate all confidence values for all resources associated with a
|
||||
// page.
|
||||
// * entry - the cache entry with all necessary information about this page
|
||||
// * lastLoad - timestamp of the last time this page was loaded
|
||||
// * loadCount - number of times this page has been loaded
|
||||
// * gloablDegradation - value calculated by CalculateGlobalDegradation for
|
||||
// this page
|
||||
void CalculatePredictions(nsICacheEntry *entry, uint32_t lastLoad,
|
||||
uint32_t loadCount, int32_t globalDegradation);
|
||||
|
||||
// Used to prepare any necessary prediction for a resource on a page
|
||||
// * confidence - value calculated by CalculateConfidence for this resource
|
||||
// * uri - the URI of the resource
|
||||
void SetupPrediction(int32_t confidence, nsIURI *uri);
|
||||
|
||||
// Used to actually perform any predictions set up via SetupPrediction.
|
||||
// Returns true if any predictions were performed.
|
||||
// * verifier - used for testing to ensure the expected predictions happen
|
||||
bool RunPredictions(nsINetworkPredictorVerifier *verifier);
|
||||
|
||||
// Used to guess whether a page will redirect to another page or not. Returns
|
||||
// true if a redirection is likely.
|
||||
// * entry - cache entry with all necessary information about this page
|
||||
// * loadCount - number of times this page has been loaded
|
||||
// * lastLoad - timestamp of the last time this page was loaded
|
||||
// * globalDegradation - value calculated by CalculateGlobalDegradation for
|
||||
// this page
|
||||
// * redirectURI - if this returns true, the URI that is likely to be
|
||||
// redirected to, otherwise null
|
||||
bool WouldRedirect(nsICacheEntry *entry, uint32_t loadCount,
|
||||
uint32_t lastLoad, int32_t globalDegradation,
|
||||
nsIURI **redirectURI);
|
||||
|
||||
// The guts of learning information
|
||||
|
||||
// This is the top-level driver for doing any updating of our information in
|
||||
// the cache
|
||||
// * reason - why this learn is happening (pageload, startup, redirect)
|
||||
// * entry - the cache entry with the information we need
|
||||
// * isNew - whether or not the cache entry is brand new and empty
|
||||
// * fullUri - whether we are doing predictions based on a full page URI, or
|
||||
// just the origin of the page
|
||||
// * targetURI - the URI that we are adding to our data - most often a
|
||||
// resource loaded by a page the user navigated to
|
||||
// * sourceURI - the URI that caused targetURI to be loaded, usually the
|
||||
// page the user navigated to
|
||||
void LearnInternal(PredictorLearnReason reason, nsICacheEntry *entry,
|
||||
bool isNew, bool fullUri, nsIURI *targetURI,
|
||||
nsIURI *sourceURI);
|
||||
|
||||
// Used when learning about a resource loaded by a page
|
||||
// * entry - the cache entry with information that needs updating
|
||||
// * targetURI - the URI of the resource that was loaded by the page
|
||||
void LearnForSubresource(nsICacheEntry *entry, nsIURI *targetURI);
|
||||
|
||||
// Used when learning about a redirect from one page to another
|
||||
// * entry - the cache entry of the page that was redirected from
|
||||
// * targetURI - the URI of the redirect target
|
||||
void LearnForRedirect(nsICacheEntry *entry, nsIURI *targetURI);
|
||||
|
||||
// Used to learn about pages loaded close to browser startup. This results in
|
||||
// LearnForStartup being called if we are, in fact, near browser startup
|
||||
// * uri - the URI of a page that has been loaded (may not have been near
|
||||
// browser startup)
|
||||
// * fullUri - true if this is a full page uri, false if it's an origin
|
||||
void MaybeLearnForStartup(nsIURI *uri, bool fullUri);
|
||||
|
||||
// Used in conjunction with MaybeLearnForStartup to learn about pages loaded
|
||||
// close to browser startup
|
||||
// * entry - the cache entry that stores the startup page list
|
||||
// * targetURI - the URI of a page that was loaded near browser startup
|
||||
void LearnForStartup(nsICacheEntry *entry, nsIURI *targetURI);
|
||||
|
||||
// Used to parse the data we store in cache metadata
|
||||
// * key - the cache metadata key
|
||||
// * value - the cache metadata value
|
||||
// * uri - (out) the URI this metadata entry was about
|
||||
// * hitCount - (out) the number of times this URI has been seen
|
||||
// * lastHit - (out) timestamp of the last time this URI was seen
|
||||
// * flags - (out) flags for this metadata entry
|
||||
bool ParseMetaDataEntry(const char *key, const char *value, nsIURI **uri,
|
||||
uint32_t &hitCount, uint32_t &lastHit,
|
||||
uint32_t &flags);
|
||||
|
||||
// Our state
|
||||
bool mInitialized;
|
||||
|
||||
bool mEnabled;
|
||||
bool mEnableHoverOnSSL;
|
||||
|
||||
int mPageDegradationDay;
|
||||
int mPageDegradationWeek;
|
||||
int mPageDegradationMonth;
|
||||
int mPageDegradationYear;
|
||||
int mPageDegradationMax;
|
||||
int32_t mPageDegradationDay;
|
||||
int32_t mPageDegradationWeek;
|
||||
int32_t mPageDegradationMonth;
|
||||
int32_t mPageDegradationYear;
|
||||
int32_t mPageDegradationMax;
|
||||
|
||||
int mSubresourceDegradationDay;
|
||||
int mSubresourceDegradationWeek;
|
||||
int mSubresourceDegradationMonth;
|
||||
int mSubresourceDegradationYear;
|
||||
int mSubresourceDegradationMax;
|
||||
int32_t mSubresourceDegradationDay;
|
||||
int32_t mSubresourceDegradationWeek;
|
||||
int32_t mSubresourceDegradationMonth;
|
||||
int32_t mSubresourceDegradationYear;
|
||||
int32_t mSubresourceDegradationMax;
|
||||
|
||||
int mPreconnectMinConfidence;
|
||||
int mPreresolveMinConfidence;
|
||||
int mRedirectLikelyConfidence;
|
||||
int32_t mPreconnectMinConfidence;
|
||||
int32_t mPreresolveMinConfidence;
|
||||
int32_t mRedirectLikelyConfidence;
|
||||
|
||||
int32_t mMaxQueueSize;
|
||||
int32_t mMaxResourcesPerEntry;
|
||||
|
||||
nsCOMPtr<nsIThread> mIOThread;
|
||||
bool mCleanedUp;
|
||||
nsCOMPtr<nsITimer> mCleanupTimer;
|
||||
|
||||
nsTArray<nsCString> mKeysToOperateOn;
|
||||
nsTArray<nsCString> mValuesToOperateOn;
|
||||
|
||||
nsCOMPtr<nsICacheStorage> mCacheDiskStorage;
|
||||
|
||||
nsCOMPtr<nsIIOService> mIOService;
|
||||
nsCOMPtr<nsISpeculativeConnect> mSpeculativeService;
|
||||
|
||||
nsCOMPtr<nsIFile> mDBFile;
|
||||
nsCOMPtr<mozIStorageService> mStorageService;
|
||||
nsCOMPtr<mozIStorageConnection> mDB;
|
||||
mozilla::storage::StatementCache<mozIStorageStatement> mStatements;
|
||||
|
||||
PRTime mStartupTime;
|
||||
PRTime mLastStartupTime;
|
||||
nsCOMPtr<nsIURI> mStartupURI;
|
||||
uint32_t mStartupTime;
|
||||
uint32_t mLastStartupTime;
|
||||
int32_t mStartupCount;
|
||||
|
||||
nsCOMPtr<nsIDNSService> mDnsService;
|
||||
|
||||
int32_t mQueueSize;
|
||||
mozilla::Mutex mQueueSizeLock;
|
||||
nsRefPtr<DNSListener> mDNSListener;
|
||||
|
||||
nsRefPtr<PredictorDNSListener> mDNSListener;
|
||||
nsTArray<nsCOMPtr<nsIURI>> mPreconnects;
|
||||
nsTArray<nsCOMPtr<nsIURI>> mPreresolves;
|
||||
|
||||
nsCOMPtr<nsITimer> mCommitTimer;
|
||||
|
||||
#ifdef PREDICTOR_TESTS
|
||||
friend class PredictorPrepareForDnsTestEvent;
|
||||
void PrepareForDnsTestInternal(int64_t timestamp, const nsACString &uri);
|
||||
#endif
|
||||
|
||||
bool mCleanupScheduled;
|
||||
int32_t mMaxDBSize;
|
||||
int32_t mPreservePercentage;
|
||||
PRTime mLastCleanupTime;
|
||||
static Predictor *sSelf;
|
||||
};
|
||||
|
||||
} // ::mozilla::net
|
||||
|
@ -47,6 +47,7 @@ var Verifier = function _verifier(testing, expected_preconnects, expected_preres
|
||||
};
|
||||
|
||||
Verifier.prototype = {
|
||||
complete: false,
|
||||
verifying: null,
|
||||
expected_preconnects: null,
|
||||
expected_preresolves: null,
|
||||
@ -66,16 +67,19 @@ Verifier.prototype = {
|
||||
|
||||
maybe_run_next_test: function verifier_maybe_run_next_test() {
|
||||
if (this.expected_preconnects.length === 0 &&
|
||||
this.expected_preresolves.length === 0) {
|
||||
this.expected_preresolves.length === 0 &&
|
||||
!this.complete) {
|
||||
this.complete = true;
|
||||
do_check_true(true, "Well this is unexpected...");
|
||||
run_next_test();
|
||||
// This kicks off the ability to run the next test
|
||||
reset_predictor();
|
||||
}
|
||||
},
|
||||
|
||||
onPredictPreconnect: function verifier_onPredictPreconnect(uri) {
|
||||
var origin = extract_origin(uri);
|
||||
var index = this.expected_preconnects.indexOf(origin);
|
||||
if (index == -1) {
|
||||
if (index == -1 && !this.complete) {
|
||||
do_check_true(false, "Got preconnect for unexpected uri " + origin);
|
||||
} else {
|
||||
this.expected_preconnects.splice(index, 1);
|
||||
@ -86,7 +90,7 @@ Verifier.prototype = {
|
||||
onPredictDNS: function verifier_onPredictDNS(uri) {
|
||||
var origin = extract_origin(uri);
|
||||
var index = this.expected_preresolves.indexOf(origin);
|
||||
if (index == -1) {
|
||||
if (index == -1 && !this.complete) {
|
||||
do_check_true(false, "Got preresolve for unexpected uri " + origin);
|
||||
} else {
|
||||
this.expected_preresolves.splice(index, 1);
|
||||
@ -103,8 +107,66 @@ function newURI(s) {
|
||||
return ios.newURI(s, null, null);
|
||||
}
|
||||
|
||||
var prepListener = {
|
||||
numEntriesToOpen: 0,
|
||||
numEntriesOpened: 0,
|
||||
continueCallback: null,
|
||||
|
||||
QueryInterface: function (iid) {
|
||||
if (iid.equals(Ci.nsICacheEntryOpenCallback)) {
|
||||
return this;
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
init: function (entriesToOpen, cb) {
|
||||
this.numEntriesOpened = 0;
|
||||
this.numEntriesToOpen = entriesToOpen;
|
||||
this.continueCallback = cb;
|
||||
},
|
||||
|
||||
onCacheEntryCheck: function (entry, appCache) {
|
||||
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
|
||||
},
|
||||
|
||||
onCacheEntryAvailable: function (entry, isNew, appCache, result) {
|
||||
do_check_eq(result, Cr.NS_OK);
|
||||
entry.setMetaDataElement("predictor_test", "1");
|
||||
entry.metaDataReady();
|
||||
this.numEntriesOpened++;
|
||||
if (this.numEntriesToOpen == this.numEntriesOpened) {
|
||||
this.continueCallback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function open_and_continue(uris, continueCallback) {
|
||||
var lci = {
|
||||
QueryInterface: function (iid) {
|
||||
if (iid.equals(Ci.nsILoadContextInfo)) {
|
||||
return this;
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
isPrivate: false,
|
||||
appId: Ci.nsILoadContextInfo.NO_APP_ID,
|
||||
isInBrowserElement: false,
|
||||
isAnonymous: false
|
||||
};
|
||||
|
||||
var css = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Ci.nsICacheStorageService);
|
||||
var ds = css.diskCacheStorage(lci, false);
|
||||
|
||||
prepListener.init(uris.length, continueCallback);
|
||||
for (var i = 0; i < uris.length; ++i) {
|
||||
ds.asyncOpenURI(uris[i], "", Ci.nsICacheStorage.OPEN_NORMALLY,
|
||||
prepListener);
|
||||
}
|
||||
}
|
||||
|
||||
function test_link_hover() {
|
||||
reset_predictor();
|
||||
var uri = newURI("http://localhost:4444/foo/bar");
|
||||
var referrer = newURI("http://localhost:4444/foo");
|
||||
var preconns = ["http://localhost:4444"];
|
||||
@ -114,7 +176,6 @@ function test_link_hover() {
|
||||
}
|
||||
|
||||
function test_pageload() {
|
||||
reset_predictor();
|
||||
var toplevel = "http://localhost:4444/index.html";
|
||||
var subresources = [
|
||||
"http://localhost:4444/style.css",
|
||||
@ -123,20 +184,22 @@ function test_pageload() {
|
||||
];
|
||||
|
||||
var tluri = newURI(toplevel);
|
||||
predictor.learn(tluri, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
var preconns = [];
|
||||
for (var i = 0; i < subresources.length; i++) {
|
||||
var sruri = newURI(subresources[i]);
|
||||
predictor.learn(sruri, tluri, predictor.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
preconns.push(extract_origin(sruri));
|
||||
}
|
||||
open_and_continue([tluri], function () {
|
||||
// This is necessary to learn the origin stuff
|
||||
predictor.learn(tluri, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
var preconns = [];
|
||||
for (var i = 0; i < subresources.length; i++) {
|
||||
var sruri = newURI(subresources[i]);
|
||||
predictor.learn(sruri, tluri, predictor.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
preconns.push(extract_origin(sruri));
|
||||
}
|
||||
|
||||
var verifier = new Verifier("pageload", preconns, []);
|
||||
predictor.predict(tluri, null, predictor.PREDICT_LOAD, load_context, verifier);
|
||||
var verifier = new Verifier("pageload", preconns, []);
|
||||
predictor.predict(tluri, null, predictor.PREDICT_LOAD, load_context, verifier);
|
||||
});
|
||||
}
|
||||
|
||||
function test_redirect() {
|
||||
reset_predictor();
|
||||
var initial = "http://localhost:4443/redirect";
|
||||
var target = "http://localhost:4444/index.html";
|
||||
var subresources = [
|
||||
@ -147,24 +210,25 @@ function test_redirect() {
|
||||
|
||||
var inituri = newURI(initial);
|
||||
var targeturi = newURI(target);
|
||||
predictor.learn(inituri, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
predictor.learn(targeturi, inituri, predictor.LEARN_LOAD_REDIRECT, load_context);
|
||||
predictor.learn(targeturi, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
open_and_continue([inituri, targeturi], function () {
|
||||
predictor.learn(inituri, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
predictor.learn(targeturi, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
predictor.learn(targeturi, inituri, predictor.LEARN_LOAD_REDIRECT, load_context);
|
||||
|
||||
var preconns = [];
|
||||
preconns.push(extract_origin(targeturi));
|
||||
for (var i = 0; i < subresources.length; i++) {
|
||||
var sruri = newURI(subresources[i]);
|
||||
predictor.learn(sruri, targeturi, predictor.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
preconns.push(extract_origin(sruri));
|
||||
}
|
||||
var preconns = [];
|
||||
preconns.push(extract_origin(targeturi));
|
||||
for (var i = 0; i < subresources.length; i++) {
|
||||
var sruri = newURI(subresources[i]);
|
||||
predictor.learn(sruri, targeturi, predictor.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
preconns.push(extract_origin(sruri));
|
||||
}
|
||||
|
||||
var verifier = new Verifier("redirect", preconns, []);
|
||||
predictor.predict(inituri, null, predictor.PREDICT_LOAD, load_context, verifier);
|
||||
var verifier = new Verifier("redirect", preconns, []);
|
||||
predictor.predict(inituri, null, predictor.PREDICT_LOAD, load_context, verifier);
|
||||
});
|
||||
}
|
||||
|
||||
function test_startup() {
|
||||
reset_predictor();
|
||||
var uris = [
|
||||
"http://localhost:4444/startup",
|
||||
"http://localhost:4443/startup"
|
||||
@ -180,72 +244,26 @@ function test_startup() {
|
||||
predictor.predict(null, null, predictor.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 predictor 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.nsINetworkPredictorVerifier)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
onPredictPreconnect: function _dnsContinueVerifier_onPredictPreconnect() {
|
||||
// This means that the predictor 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);
|
||||
|
||||
predictor.prepareForDnsTest(tstamp, this.subresource);
|
||||
|
||||
var verifier = new Verifier("dns", [], this.preresolves);
|
||||
predictor.predict(this.tluri, null, predictor.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_predictor();
|
||||
var toplevel = "http://localhost:4444/index.html";
|
||||
var subresource = "http://localhost:4443/jquery.js";
|
||||
|
||||
var tluri = newURI(toplevel);
|
||||
predictor.learn(tluri, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
var sruri = newURI(subresource);
|
||||
predictor.learn(sruri, tluri, predictor.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
open_and_continue([tluri], function () {
|
||||
predictor.learn(tluri, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
var sruri = newURI(subresource);
|
||||
predictor.learn(sruri, tluri, predictor.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 predictor
|
||||
// thread has gotten to the point where we can update the database manually
|
||||
predictor.predict(tluri, null, predictor.PREDICT_LOAD, load_context, continue_verifier);
|
||||
// Ensure that this will do preresolves
|
||||
prefs.setIntPref("network.predictor.preconnect-min-confidence", 101);
|
||||
|
||||
var preresolves = [extract_origin(sruri)];
|
||||
var verifier = new Verifier("dns", [], preresolves);
|
||||
predictor.predict(tluri, null, predictor.PREDICT_LOAD, load_context, verifier);
|
||||
});
|
||||
}
|
||||
|
||||
function test_origin() {
|
||||
reset_predictor();
|
||||
var toplevel = "http://localhost:4444/index.html";
|
||||
var subresources = [
|
||||
"http://localhost:4444/style.css",
|
||||
@ -254,46 +272,95 @@ function test_origin() {
|
||||
];
|
||||
|
||||
var tluri = newURI(toplevel);
|
||||
predictor.learn(tluri, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
var preconns = [];
|
||||
for (var i = 0; i < subresources.length; i++) {
|
||||
var sruri = newURI(subresources[i]);
|
||||
predictor.learn(sruri, tluri, predictor.LEARN_LOAD_SUBRESOURCE, load_context);
|
||||
var origin = extract_origin(sruri);
|
||||
if (preconns.indexOf(origin) === -1) {
|
||||
preconns.push(origin);
|
||||
open_and_continue([tluri], function () {
|
||||
predictor.learn(tluri, null, predictor.LEARN_LOAD_TOPLEVEL, load_context);
|
||||
var preconns = [];
|
||||
for (var i = 0; i < subresources.length; i++) {
|
||||
var sruri = newURI(subresources[i]);
|
||||
predictor.learn(sruri, tluri, predictor.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, []);
|
||||
predictor.predict(loaduri, null, predictor.PREDICT_LOAD, load_context, verifier);
|
||||
var loaduri = newURI("http://localhost:4444/anotherpage.html");
|
||||
var verifier = new Verifier("origin", preconns, []);
|
||||
predictor.predict(loaduri, null, predictor.PREDICT_LOAD, load_context, verifier);
|
||||
});
|
||||
}
|
||||
|
||||
var prefs;
|
||||
var predictor_pref;
|
||||
var preconnect_min_pref;
|
||||
var cleaned_up_pref;
|
||||
|
||||
function cleanup() {
|
||||
reset_predictor();
|
||||
observer.cleaningUp = true;
|
||||
predictor.reset();
|
||||
prefs.setIntPref("network.predictor.preconnect-min-confidence", preconnect_min_pref);
|
||||
prefs.setBoolPref("network.predictor.enabled", predictor_pref);
|
||||
prefs.setBoolPref("network.predictor.cleaned-up", cleaned_up_pref);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// This must ALWAYS come first, to ensure a clean slate
|
||||
reset_predictor,
|
||||
test_link_hover,
|
||||
test_pageload,
|
||||
test_redirect,
|
||||
test_startup,
|
||||
// TODO: These are disabled until the features are re-written
|
||||
//test_redirect,
|
||||
//test_startup,
|
||||
// END DISABLED TESTS
|
||||
test_origin,
|
||||
test_dns,
|
||||
test_origin
|
||||
// This must ALWAYS come last, to ensure we clean up after ourselves
|
||||
cleanup
|
||||
];
|
||||
|
||||
var observer = {
|
||||
cleaningUp: false,
|
||||
|
||||
QueryInterface: function (iid) {
|
||||
if (iid.equals(Ci.nsIObserver) ||
|
||||
iid.equals(Ci.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
observe: function (subject, topic, data) {
|
||||
if (topic != "predictor-reset-complete") {
|
||||
return;
|
||||
}
|
||||
if (this.cleaningUp) {
|
||||
unregisterObserver();
|
||||
}
|
||||
run_next_test();
|
||||
}
|
||||
};
|
||||
|
||||
function registerObserver() {
|
||||
var svc = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
svc.addObserver(observer, "predictor-reset-complete", false);
|
||||
}
|
||||
|
||||
function unregisterObserver() {
|
||||
var svc = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
svc.removeObserver(observer, "predictor-reset-complete");
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
tests.forEach(add_test);
|
||||
profile = do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
preconnect_min_pref = prefs.getIntPref("network.predictor.preconnect-min-confidence");
|
||||
predictor_pref = prefs.getBoolPref("network.predictor.enabled");
|
||||
cleaned_up_pref = prefs.getBoolPref("network.predictor.cleaned-up");
|
||||
prefs.setBoolPref("network.predictor.enabled", true);
|
||||
prefs.setBoolPref("network.predictor.cleaned-up", true);
|
||||
predictor = Cc["@mozilla.org/network/predictor;1"].getService(Ci.nsINetworkPredictor);
|
||||
do_register_cleanup(cleanup);
|
||||
registerObserver();
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -2228,13 +2228,13 @@
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Number of times nsINetworkPredictor::Learn doesn't continue because the queue is full"
|
||||
},
|
||||
"PREDICTOR_PREDICT_WAIT_TIME": {
|
||||
"PREDICTOR_WAIT_TIME": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
"n_buckets": 10,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Amount of time a predict event waits in the queue (ms)"
|
||||
"description": "Amount of time a predictor event waits in the queue (ms)"
|
||||
},
|
||||
"PREDICTOR_PREDICT_WORK_TIME": {
|
||||
"expires_in_version": "never",
|
||||
@ -2244,14 +2244,6 @@
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Amount of time spent doing the work for predict (ms)"
|
||||
},
|
||||
"PREDICTOR_LEARN_WAIT_TIME": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
"n_buckets": 10,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Amount of time a learn event waits in the queue (ms)"
|
||||
},
|
||||
"PREDICTOR_LEARN_WORK_TIME": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
|
Loading…
Reference in New Issue
Block a user