зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1361900: Part 9 - Sort scripts by initial load time before saving. r=erahm
MozReview-Commit-ID: 54UN2DVK4xM --HG-- extra : rebase_source : f7cb39eb05bb86a03a17b97cbe2cb9d8dd1008fe
This commit is contained in:
Родитель
ac38356cdd
Коммит
220b0239c3
|
@ -47,6 +47,7 @@ ScriptCacheChild::Finalize(LinkedList<ScriptPreloader::CachedScript>& scripts)
|
|||
|
||||
data->url() = script->mURL;
|
||||
data->cachePath() = script->mCachePath;
|
||||
data->loadTime() = script->mLoadTime;
|
||||
|
||||
if (script->HasBuffer()) {
|
||||
auto& xdrData = script->Buffer();
|
||||
|
@ -83,7 +84,7 @@ ScriptCacheParent::Recv__delete__(nsTArray<ScriptData>&& scripts)
|
|||
auto& cache = ScriptPreloader::GetChildSingleton();
|
||||
for (auto& script : scripts) {
|
||||
cache.NoteScript(script.url(), script.cachePath(), processType,
|
||||
Move(script.xdrData()));
|
||||
Move(script.xdrData()), script.loadTime());
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
|
|
|
@ -498,7 +498,7 @@ ScriptPreloader::InitCacheInternal()
|
|||
for (auto script : mRestoredScripts) {
|
||||
// Only async decode scripts which have been used in this process type.
|
||||
if (script->mProcessTypes.contains(CurrentProcessType()) &&
|
||||
script->mSize > MIN_OFFTHREAD_SIZE &&
|
||||
script->AsyncDecodable() &&
|
||||
JS::CanCompileOffThread(cx, options, script->mSize)) {
|
||||
DecodeScriptOffThread(cx, script);
|
||||
} else {
|
||||
|
@ -555,8 +555,6 @@ ScriptPreloader::PrepareCacheWrite()
|
|||
|
||||
AutoSafeJSAPI jsapi;
|
||||
|
||||
LinkedList<CachedScript> asyncScripts;
|
||||
|
||||
for (CachedScript* next = mSavedScripts.getFirst(); next; ) {
|
||||
CachedScript* script = next;
|
||||
next = script->getNext();
|
||||
|
@ -579,20 +577,9 @@ ScriptPreloader::PrepareCacheWrite()
|
|||
delete script;
|
||||
} else {
|
||||
script->mSize = script->Range().length();
|
||||
|
||||
if (script->mSize > MIN_OFFTHREAD_SIZE) {
|
||||
script->remove();
|
||||
asyncScripts.insertBack(script);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store async-decoded scripts contiguously, since they're loaded
|
||||
// immediately at startup.
|
||||
while (CachedScript* s = asyncScripts.popLast()) {
|
||||
mSavedScripts.insertFront(s);
|
||||
}
|
||||
|
||||
mDataPrepared = true;
|
||||
}
|
||||
|
||||
|
@ -641,9 +628,19 @@ ScriptPreloader::WriteCache()
|
|||
AutoFDClose fd;
|
||||
NS_TRY(cacheFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE, 0644, &fd.rwget()));
|
||||
|
||||
nsTArray<CachedScript*> scripts;
|
||||
for (auto script : mSavedScripts) {
|
||||
scripts.AppendElement(script);
|
||||
}
|
||||
|
||||
// Sort scripts by load time, with async loaded scripts before sync scripts.
|
||||
// Since async scripts are always loaded immediately at startup, it helps to
|
||||
// have them stored contiguously.
|
||||
scripts.Sort(CachedScript::Comparator());
|
||||
|
||||
OutputBuffer buf;
|
||||
size_t offset = 0;
|
||||
for (auto script : mSavedScripts) {
|
||||
for (auto script : scripts) {
|
||||
script->mOffset = offset;
|
||||
script->Code(buf);
|
||||
|
||||
|
@ -656,8 +653,7 @@ ScriptPreloader::WriteCache()
|
|||
MOZ_TRY(Write(fd, MAGIC, sizeof(MAGIC)));
|
||||
MOZ_TRY(Write(fd, headerSize, sizeof(headerSize)));
|
||||
MOZ_TRY(Write(fd, buf.Get(), buf.cursor()));
|
||||
|
||||
for (auto script : mSavedScripts) {
|
||||
for (auto script : scripts) {
|
||||
MOZ_TRY(Write(fd, script->Range().begin().get(), script->mSize));
|
||||
|
||||
if (script->mScript) {
|
||||
|
@ -739,12 +735,14 @@ ScriptPreloader::NoteScript(const nsCString& url, const nsCString& cachePath,
|
|||
return;
|
||||
}
|
||||
|
||||
script->UpdateLoadTime(TimeStamp::Now());
|
||||
script->mProcessTypes += CurrentProcessType();
|
||||
}
|
||||
|
||||
void
|
||||
ScriptPreloader::NoteScript(const nsCString& url, const nsCString& cachePath,
|
||||
ProcessType processType, nsTArray<uint8_t>&& xdrData)
|
||||
ProcessType processType, nsTArray<uint8_t>&& xdrData,
|
||||
TimeStamp loadTime)
|
||||
{
|
||||
CachedScript* script = mScripts.Get(cachePath);
|
||||
bool restored = script && FindScript(mRestoredScripts, cachePath);
|
||||
|
@ -772,6 +770,7 @@ ScriptPreloader::NoteScript(const nsCString& url, const nsCString& cachePath,
|
|||
}
|
||||
}
|
||||
|
||||
script->UpdateLoadTime(loadTime);
|
||||
script->mProcessTypes += processType;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,8 @@ public:
|
|||
void NoteScript(const nsCString& url, const nsCString& cachePath, JS::HandleScript script);
|
||||
|
||||
void NoteScript(const nsCString& url, const nsCString& cachePath,
|
||||
ProcessType processType, nsTArray<uint8_t>&& xdrData);
|
||||
ProcessType processType, nsTArray<uint8_t>&& xdrData,
|
||||
TimeStamp loadTime);
|
||||
|
||||
// Initializes the script cache from the startup script cache file.
|
||||
Result<Ok, nsresult> InitCache(const nsAString& = NS_LITERAL_STRING("scriptCache"));
|
||||
|
@ -148,6 +149,33 @@ private:
|
|||
mCache->mScripts.Remove(mCachePath);
|
||||
}
|
||||
|
||||
// For use with nsTArray::Sort.
|
||||
//
|
||||
// Orders scripts by:
|
||||
//
|
||||
// 1) Async-decoded scripts before sync-decoded scripts, since the
|
||||
// former are needed immediately at startup, and should be stored
|
||||
// contiguously.
|
||||
// 2) Script load time, so that scripts which are needed earlier are
|
||||
// stored earlier, and scripts needed at approximately the same
|
||||
// time are stored approximately contiguously.
|
||||
struct Comparator
|
||||
{
|
||||
bool Equals(const CachedScript* a, const CachedScript* b) const
|
||||
{
|
||||
return (a->AsyncDecodable() == b->AsyncDecodable() &&
|
||||
a->mLoadTime == b->mLoadTime);
|
||||
}
|
||||
|
||||
bool LessThan(const CachedScript* a, const CachedScript* b) const
|
||||
{
|
||||
if (a->AsyncDecodable() != b->AsyncDecodable()) {
|
||||
return a->AsyncDecodable();
|
||||
}
|
||||
return a->mLoadTime < b->mLoadTime;
|
||||
}
|
||||
};
|
||||
|
||||
void Cancel();
|
||||
|
||||
void FreeData()
|
||||
|
@ -160,6 +188,15 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void UpdateLoadTime(const TimeStamp& loadTime)
|
||||
{
|
||||
if (!mLoadTime || loadTime < mLoadTime) {
|
||||
mLoadTime = loadTime;
|
||||
}
|
||||
}
|
||||
|
||||
bool AsyncDecodable() const { return mSize > MIN_OFFTHREAD_SIZE; }
|
||||
|
||||
// Encodes this script into XDR data, and stores the result in mXDRData.
|
||||
// Returns true on success, false on failure.
|
||||
bool XDREncode(JSContext* cx);
|
||||
|
@ -237,6 +274,8 @@ private:
|
|||
// The size of this script's encoded XDR data.
|
||||
uint32_t mSize = 0;
|
||||
|
||||
TimeStamp mLoadTime{};
|
||||
|
||||
JS::Heap<JSScript*> mScript;
|
||||
|
||||
// True if this script is ready to be executed. This means that either the
|
||||
|
|
Загрузка…
Ссылка в новой задаче