Bug 1736057 - Enable off thread full parsing by default for external JS scripts r=smaug,bas

The results from a nightly experiment, found at https://protosaur.dev/partybal/bug_1722551_pref_full_js_parsing_experiment_nightly_94_94.html, indicate that there is a 2% improvement in the page load time by enabling full parsing for external JS scripts.  This is most noticeable in the low cpu segment, where improvements of up to 10% can be seen.  This all comes at a memory increase of about 1% in the median, and 4% in the worst case.

Differential Revision: https://phabricator.services.mozilla.com/D129158
This commit is contained in:
Denis Palmeiro 2021-10-25 14:54:26 +00:00
Родитель 29d1532e4f
Коммит a728edfd6d
3 изменённых файлов: 86 добавлений и 10 удалений

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

@ -227,6 +227,8 @@ ScriptLoader::ScriptLoader(Document* aDocument)
mParserBlockingBlockerCount(0),
mBlockerCount(0),
mNumberOfProcessors(0),
mTotalFullParseSize(0),
mPhysicalSizeOfMemory(-1),
mEnabled(true),
mDeferEnabled(false),
mSpeculativeOMTParsingEnabled(false),
@ -2582,14 +2584,25 @@ nsresult ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
}
} else {
MOZ_ASSERT(aRequest->IsTextSource());
if (ShouldFullParse(aRequest)) {
options.setForceFullParse();
mTotalFullParseSize +=
aRequest->ScriptTextLength() > 0
? static_cast<uint32_t>(aRequest->ScriptTextLength())
: 0;
LOG(
("ScriptLoadRequest (%p): Full Parsing Enabled for url=%s "
"mTotalFullParseSize=%u",
aRequest, aRequest->mURI->GetSpecOrDefault().get(),
mTotalFullParseSize));
}
MaybeSourceText maybeSource;
nsresult rv = GetScriptSource(cx, aRequest, &maybeSource);
NS_ENSURE_SUCCESS(rv, rv);
if (StaticPrefs::dom_script_loader_full_parse()) {
options.setForceFullParse();
}
aRequest->mOffThreadToken =
maybeSource.constructed<SourceText<char16_t>>()
? JS::CompileOffThread(
@ -4083,18 +4096,69 @@ void ScriptLoader::ContinueParserAsync(
}
uint32_t ScriptLoader::NumberOfProcessors() {
if (mNumberOfProcessors > 0) return mNumberOfProcessors;
if (mNumberOfProcessors > 0) {
return mNumberOfProcessors;
}
int32_t numProcs = PR_GetNumberOfProcessors();
if (numProcs > 0) mNumberOfProcessors = numProcs;
if (numProcs > 0) {
mNumberOfProcessors = numProcs;
}
return mNumberOfProcessors;
}
int32_t ScriptLoader::PhysicalSizeOfMemoryInGB() {
// 0 is a valid result from PR_GetPhysicalMemorySize() which
// means a failure occured.
if (mPhysicalSizeOfMemory >= 0) {
return mPhysicalSizeOfMemory;
}
// Save the size in GB.
mPhysicalSizeOfMemory =
static_cast<int32_t>(PR_GetPhysicalMemorySize() >> 30);
return mPhysicalSizeOfMemory;
}
static bool IsInternalURIScheme(nsIURI* uri) {
return uri->SchemeIs("moz-extension") || uri->SchemeIs("resource") ||
uri->SchemeIs("chrome");
}
bool ScriptLoader::ShouldFullParse(ScriptLoadRequest* aRequest) {
// Full parse everything if negative.
if (StaticPrefs::dom_script_loader_full_parse_max_size() < 0) {
return true;
}
// Be conservative on machines with 2GB or less of memory.
if (PhysicalSizeOfMemoryInGB() <=
StaticPrefs::dom_script_loader_full_parse_min_mem()) {
return false;
}
uint32_t max_size = static_cast<uint32_t>(
StaticPrefs::dom_script_loader_full_parse_max_size());
uint32_t script_size =
aRequest->ScriptTextLength() > 0
? static_cast<uint32_t>(aRequest->ScriptTextLength())
: 0;
if (mTotalFullParseSize + script_size < max_size) {
return true;
}
if (LOG_ENABLED()) {
nsCString url = aRequest->mURI->GetSpecOrDefault();
LOG(
("ScriptLoadRequest (%p): Full Parsing Disabled for (%s) with size=%u"
" because mTotalFullParseSize=%u would exceed max_size=%u",
aRequest, url.get(), script_size, mTotalFullParseSize, max_size));
}
return false;
}
bool ScriptLoader::ShouldCompileOffThread(ScriptLoadRequest* aRequest) {
if (NumberOfProcessors() <= 1) {
return false;

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

@ -623,6 +623,8 @@ class ScriptLoader final : public nsISupports {
JS::MutableHandle<JSScript*> aIntroductionScript);
uint32_t NumberOfProcessors();
int32_t PhysicalSizeOfMemoryInGB();
nsresult PrepareLoadedRequest(ScriptLoadRequest* aRequest,
nsIIncrementalStreamLoader* aLoader,
nsresult aStatus);
@ -631,6 +633,7 @@ class ScriptLoader final : public nsISupports {
void AddAsyncRequest(ScriptLoadRequest* aRequest);
bool MaybeRemovedDeferRequests();
bool ShouldFullParse(ScriptLoadRequest* aRequest);
bool ShouldCompileOffThread(ScriptLoadRequest* aRequest);
void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
@ -730,6 +733,8 @@ class ScriptLoader final : public nsISupports {
uint32_t mParserBlockingBlockerCount;
uint32_t mBlockerCount;
uint32_t mNumberOfProcessors;
uint32_t mTotalFullParseSize;
int32_t mPhysicalSizeOfMemory;
bool mEnabled;
bool mDeferEnabled;
bool mSpeculativeOMTParsingEnabled;

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

@ -3039,10 +3039,17 @@
value: 0
mirror: always
# Force full parse on any external JS scripts that is being compiled off thread.
- name: dom.script_loader.full_parse
type: bool
value: false
# Maximum total size for all full parsed scripts in each ScriptLoader instance.
# -1 implies full parse everything. Default value is 10MB for utf8 scripts.
- name: dom.script_loader.full_parse_max_size
type: int32_t
value: 10485760
mirror: always
# Minimum memory, in GB, required to enable full parsing.
- name: dom.script_loader.full_parse_min_mem
type: int32_t
value: 2
mirror: always
# Is support for decoding external (non-inline) classic or module DOM scripts