Bug 1009122 - use cache2 as storage for predictor data. r=honzab

--HG--
extra : rebase_source : 290e1aa04a1dfa2e7d6cb9f1b5b705d1ed80e68c
This commit is contained in:
Nicholas Hurley 2015-01-14 13:59:04 -08:00
Родитель 8a22ce4bd0
Коммит 87facfa179
9 изменённых файлов: 1660 добавлений и 2471 удалений

Просмотреть файл

@ -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++

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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",