зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1343483 - Determine how long functions remain syntax-parsed before they are full-parsed;r=shu
In many cases, to speed up start, compiling a ScriptSource will not compile the functions themselves, but will rather syntax-parse them (to check for syntax errors), leaving full compilation for later. However, if we find ourselves in a case in which the function is needed almost immediately, we need to full-parse the function immediately after the syntax-parse, which is wasteful. This changeset intends to measure how often this happens, by exporting through Telemetry the duration between the end of the syntax-parse and the start of the full-parse for each function. As a memory optimization, instead of storing a timestamp for the syntax-parse of each function, we store a single timestamp for an entire ScriptSource. This assumes that all functions of the ScriptSource are syntax-parsed at approximately the same instant, which should be mostly true for everything except perhaps `eval` and `new Function`. Then, when time comes to delazify a function, we simply determine the time elapsed since the ScriptSource was compiled. Histogram JS_PARSER_COMPILE_LAZY_AFTER_MS starts at 10ms (anything smaller is often not measurable) and stops at 10s (anything larger can safely be said to be not wasteful). MozReview-Commit-ID: 6Ycy2OIIiAt --HG-- extra : rebase_source : 0ccd6f51189b3ad8056e9f39e267235d68f6e2db
This commit is contained in:
Родитель
88008d0832
Коммит
c1b5f21196
|
@ -397,6 +397,10 @@ BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
|
|||
if (!maybeCompleteCompressSource())
|
||||
return nullptr;
|
||||
|
||||
// We have just finished parsing the source. Inform the source so that we
|
||||
// can compute statistics (e.g. how much time our functions remain lazy).
|
||||
script->scriptSource()->recordParseEnded();
|
||||
|
||||
MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
|
||||
|
||||
return script;
|
||||
|
@ -668,6 +672,24 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
|||
.setNoScriptRval(false)
|
||||
.setSelfHostingMode(false);
|
||||
|
||||
// Update statistics to find out if we are delazifying just after having
|
||||
// lazified. Note that we are interested in the delta between end of
|
||||
// syntax parsing and start of full parsing, so we do this now rather than
|
||||
// after parsing below.
|
||||
if (!lazy->scriptSource()->parseEnded().IsNull()) {
|
||||
const mozilla::TimeDuration delta = mozilla::TimeStamp::Now() -
|
||||
lazy->scriptSource()->parseEnded();
|
||||
|
||||
// Differentiate between web-facing and privileged code, to aid
|
||||
// with optimization. Due to the number of calls to this function,
|
||||
// we use `cx->runningWithTrustedPrincipals`, which is fast but
|
||||
// will classify addons alongside with web-facing code.
|
||||
const int HISTOGRAM = cx->runningWithTrustedPrincipals()
|
||||
? JS_TELEMETRY_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS
|
||||
: JS_TELEMETRY_WEB_PARSER_COMPILE_LAZY_AFTER_MS;
|
||||
cx->runtime()->addTelemetry(HISTOGRAM, delta.ToMilliseconds());
|
||||
}
|
||||
|
||||
UsedNameTracker usedNames(cx);
|
||||
if (!usedNames.init())
|
||||
return false;
|
||||
|
|
|
@ -136,6 +136,8 @@ enum {
|
|||
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS,
|
||||
JS_TELEMETRY_ADDON_EXCEPTIONS,
|
||||
JS_TELEMETRY_AOT_USAGE,
|
||||
JS_TELEMETRY_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS,
|
||||
JS_TELEMETRY_WEB_PARSER_COMPILE_LAZY_AFTER_MS,
|
||||
JS_TELEMETRY_END
|
||||
};
|
||||
|
||||
|
|
|
@ -445,6 +445,14 @@ class ScriptSource
|
|||
const char16_t* chunkChars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holder,
|
||||
size_t chunk);
|
||||
|
||||
// Instant at which the first parse of this source ended, or null
|
||||
// if the source hasn't been parsed yet.
|
||||
//
|
||||
// Used for statistics purposes, to determine how much time code spends
|
||||
// syntax parsed before being full parsed, to help determine whether
|
||||
// our syntax parse vs. full parse heuristics are correct.
|
||||
mozilla::TimeStamp parseEnded_;
|
||||
|
||||
public:
|
||||
explicit ScriptSource()
|
||||
: refs(0),
|
||||
|
@ -603,6 +611,15 @@ class ScriptSource
|
|||
// |xdrEncodeTopLevel|, and free the XDR encoder. In case of errors, the
|
||||
// |buffer| is considered undefined.
|
||||
bool xdrFinalizeEncoder();
|
||||
|
||||
const mozilla::TimeStamp parseEnded() const {
|
||||
return parseEnded_;
|
||||
}
|
||||
// Inform `this` source that it has been fully parsed.
|
||||
void recordParseEnded() {
|
||||
MOZ_ASSERT(parseEnded_.IsNull());
|
||||
parseEnded_ = mozilla::TimeStamp::Now();
|
||||
}
|
||||
};
|
||||
|
||||
class ScriptSourceHolder
|
||||
|
|
|
@ -3154,6 +3154,12 @@ AccumulateTelemetryCallback(int id, uint32_t sample, const char* key)
|
|||
case JS_TELEMETRY_AOT_USAGE:
|
||||
Telemetry::Accumulate(Telemetry::JS_AOT_USAGE, sample);
|
||||
break;
|
||||
case JS_TELEMETRY_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS:
|
||||
Telemetry::Accumulate(Telemetry::JS_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS, sample);
|
||||
break;
|
||||
case JS_TELEMETRY_WEB_PARSER_COMPILE_LAZY_AFTER_MS:
|
||||
Telemetry::Accumulate(Telemetry::JS_WEB_PARSER_COMPILE_LAZY_AFTER_MS, sample);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected JS_TELEMETRY id");
|
||||
}
|
||||
|
|
|
@ -1084,6 +1084,26 @@
|
|||
"n_values": 10,
|
||||
"description": "Use of SpiderMonkey's deprecated language extensions in add-ons: ForEach=0, DestructuringForIn=1 (obsolete), LegacyGenerator=2, ExpressionClosure=3, LetBlock=4 (obsolete), LetExpression=5 (obsolete), NoSuchMethod=6 (obsolete), FlagsArgument=7 (obsolete), RegExpSourceProp=8 (obsolete), RestoredRegExpStatics=9 (obsolete), BlockScopeFunRedecl=10"
|
||||
},
|
||||
"JS_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS": {
|
||||
"alert_emails": ["dteller@mozilla.com"],
|
||||
"expires_in_version": "70",
|
||||
"bug_numbers": [1343483],
|
||||
"kind": "exponential",
|
||||
"low": 10,
|
||||
"high": 10000,
|
||||
"n_buckets": 10,
|
||||
"description": "Time elapsed between the moment a function is lazy-parsed (end of parsing of the ScriptSource) and the moment it is recompiled as non-lazy (start of compilation), in milliseconds, for privileged code."
|
||||
},
|
||||
"JS_WEB_PARSER_COMPILE_LAZY_AFTER_MS": {
|
||||
"alert_emails": ["dteller@mozilla.com"],
|
||||
"expires_in_version": "70",
|
||||
"bug_numbers": [1343483],
|
||||
"kind": "exponential",
|
||||
"low": 10,
|
||||
"high": 10000,
|
||||
"n_buckets": 10,
|
||||
"description": "Time elapsed between the moment a function is lazy-parsed (end of parsing of the ScriptSource) and the moment it is recompiled as non-lazy (start of compilation), in milliseconds, for web code."
|
||||
},
|
||||
"XUL_CACHE_DISABLED": {
|
||||
"expires_in_version": "default",
|
||||
"kind": "flag",
|
||||
|
|
Загрузка…
Ссылка в новой задаче