Bug 1362114 - JSBC: Add telemetry to later tune the heuristics. r=mrbkap,francois
This commit is contained in:
@@ -175,6 +175,59 @@ ScriptLoader::~ScriptLoader()
|
||||
}
|
||||
}
|
||||
|
||||
// Collect telemtry data about the cache information, and the kind of source
|
||||
// which are being loaded, and where it is being loaded from.
|
||||
static void
|
||||
CollectScriptTelemetry(nsIIncrementalStreamLoader* aLoader,
|
||||
ScriptLoadRequest* aRequest)
|
||||
{
|
||||
using namespace mozilla::Telemetry;
|
||||
|
||||
// Skip this function if we are not running telemetry.
|
||||
if (!CanRecordExtended()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Report the type of source, as well as the size of the source.
|
||||
if (aRequest->IsLoadingSource()) {
|
||||
if (aRequest->mIsInline) {
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_LOADING_SOURCE::Inline);
|
||||
nsAutoString inlineData;
|
||||
aRequest->mElement->GetScriptText(inlineData);
|
||||
Accumulate(DOM_SCRIPT_INLINE_SIZE, inlineData.Length());
|
||||
} else {
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_LOADING_SOURCE::SourceFallback);
|
||||
Accumulate(DOM_SCRIPT_SOURCE_SIZE, aRequest->mScriptText.length());
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(aRequest->IsLoading());
|
||||
if (aRequest->IsSource()) {
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_LOADING_SOURCE::Source);
|
||||
Accumulate(DOM_SCRIPT_SOURCE_SIZE, aRequest->mScriptText.length());
|
||||
} else {
|
||||
MOZ_ASSERT(aRequest->IsBytecode());
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_LOADING_SOURCE::AltData);
|
||||
Accumulate(DOM_SCRIPT_BYTECODE_SIZE, aRequest->mScriptBytecode.length());
|
||||
}
|
||||
}
|
||||
|
||||
// Skip if we do not have any cache information for the given script.
|
||||
if (!aLoader) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIRequest> channel;
|
||||
aLoader->GetRequest(getter_AddRefs(channel));
|
||||
nsCOMPtr<nsICacheInfoChannel> cic(do_QueryInterface(channel));
|
||||
if (!cic) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t fetchCount = 0;
|
||||
if (NS_SUCCEEDED(cic->GetCacheTokenFetchCount(&fetchCount))) {
|
||||
Accumulate(DOM_SCRIPT_FETCH_COUNT, fetchCount);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method for checking if the script element is an event-handler
|
||||
// This means that it has both a for-attribute and a event-attribute.
|
||||
// Also, if the for-attribute has a value that matches "\s*window\s*",
|
||||
@@ -1364,6 +1417,7 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement* aElement)
|
||||
request->mProgress = ScriptLoadRequest::Progress::Loading_Source;
|
||||
request->mDataType = ScriptLoadRequest::DataType::Source;
|
||||
TRACE_FOR_TEST_BOOL(request->mElement, "scriptloader_load_source");
|
||||
CollectScriptTelemetry(nullptr, request);
|
||||
|
||||
if (request->IsModuleRequest()) {
|
||||
ModuleLoadRequest* modReq = request->AsModuleRequest();
|
||||
@@ -2002,6 +2056,7 @@ ScriptLoader::ShouldCacheBytecode(ScriptLoadRequest* aRequest)
|
||||
nsresult
|
||||
ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
|
||||
{
|
||||
using namespace mozilla::Telemetry;
|
||||
MOZ_ASSERT(aRequest->IsReadyToRun());
|
||||
|
||||
// We need a document to evaluate scripts.
|
||||
@@ -2016,6 +2071,9 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Report telemetry results of the number of scripts evaluated.
|
||||
mDocument->SetDocumentIncCounter(IncCounter::eIncCounter_ScriptTag);
|
||||
|
||||
// Get the script-type to be used by this element.
|
||||
NS_ASSERTION(scriptContent, "no content - what is default script-type?");
|
||||
|
||||
@@ -2081,9 +2139,11 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
|
||||
nsJSUtils::ExecutionContext exec(aes.cx(), global);
|
||||
if (aRequest->mOffThreadToken) {
|
||||
LOG(("ScriptLoadRequest (%p): Decode Bytecode & Join and Execute", aRequest));
|
||||
AutoTimer<DOM_SCRIPT_OFF_THREAD_DECODE_EXEC_MS> timer;
|
||||
rv = exec.DecodeJoinAndExec(&aRequest->mOffThreadToken);
|
||||
} else {
|
||||
LOG(("ScriptLoadRequest (%p): Decode Bytecode and Execute", aRequest));
|
||||
AutoTimer<DOM_SCRIPT_MAIN_THREAD_DECODE_EXEC_MS> timer;
|
||||
rv = exec.DecodeAndExec(options, aRequest->mScriptBytecode,
|
||||
aRequest->mBytecodeOffset);
|
||||
}
|
||||
@@ -2095,6 +2155,14 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
|
||||
JS::Rooted<JSScript*> script(aes.cx());
|
||||
bool encodeBytecode = ShouldCacheBytecode(aRequest);
|
||||
|
||||
TimeStamp start;
|
||||
if (Telemetry::CanRecordExtended()) {
|
||||
// Only record telemetry for scripts which are above the threshold.
|
||||
if (aRequest->mCacheInfo && aRequest->mScriptText.length() < 1024) {
|
||||
start = TimeStamp::Now();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
nsJSUtils::ExecutionContext exec(aes.cx(), global);
|
||||
exec.SetEncodeBytecode(encodeBytecode);
|
||||
@@ -2104,12 +2172,24 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
|
||||
LOG(("ScriptLoadRequest (%p): Join (off-thread parsing) and Execute",
|
||||
aRequest));
|
||||
rv = exec.JoinAndExec(&aRequest->mOffThreadToken, &script);
|
||||
if (start) {
|
||||
AccumulateTimeDelta(encodeBytecode
|
||||
? DOM_SCRIPT_OFF_THREAD_PARSE_ENCODE_EXEC_MS
|
||||
: DOM_SCRIPT_OFF_THREAD_PARSE_EXEC_MS,
|
||||
start);
|
||||
}
|
||||
} else {
|
||||
// Main thread parsing (inline and small scripts)
|
||||
LOG(("ScriptLoadRequest (%p): Compile And Exec", aRequest));
|
||||
nsAutoString inlineData;
|
||||
SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData);
|
||||
rv = exec.CompileAndExec(options, srcBuf, &script);
|
||||
if (start) {
|
||||
AccumulateTimeDelta(encodeBytecode
|
||||
? DOM_SCRIPT_MAIN_THREAD_PARSE_ENCODE_EXEC_MS
|
||||
: DOM_SCRIPT_MAIN_THREAD_PARSE_EXEC_MS,
|
||||
start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2210,6 +2290,7 @@ ScriptLoader::EncodeBytecode()
|
||||
return;
|
||||
}
|
||||
|
||||
Telemetry::AutoTimer<Telemetry::DOM_SCRIPT_ENCODING_MS_PER_DOCUMENT> timer;
|
||||
AutoEntryScript aes(globalObject, "encode bytecode", true);
|
||||
RefPtr<ScriptLoadRequest> request;
|
||||
while (!mBytecodeEncodingQueue.isEmpty()) {
|
||||
@@ -2223,6 +2304,7 @@ ScriptLoader::EncodeBytecode()
|
||||
void
|
||||
ScriptLoader::EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest)
|
||||
{
|
||||
using namespace mozilla::Telemetry;
|
||||
nsresult rv = NS_OK;
|
||||
MOZ_ASSERT(aRequest->mCacheInfo);
|
||||
auto bytecodeFailed = mozilla::MakeScopeExit([&]() {
|
||||
@@ -2233,12 +2315,14 @@ ScriptLoader::EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest)
|
||||
if (!JS::FinishIncrementalEncoding(aCx, script, aRequest->mScriptBytecode)) {
|
||||
LOG(("ScriptLoadRequest (%p): Cannot serialize bytecode",
|
||||
aRequest));
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_ENCODING_STATUS::EncodingFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRequest->mScriptBytecode.length() >= UINT32_MAX) {
|
||||
LOG(("ScriptLoadRequest (%p): Bytecode cache is too large to be decoded correctly.",
|
||||
aRequest));
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_ENCODING_STATUS::BufferTooLarge);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2251,6 +2335,7 @@ ScriptLoader::EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest)
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("ScriptLoadRequest (%p): Cannot open bytecode cache (rv = %X, output = %p)",
|
||||
aRequest, unsigned(rv), output.get()));
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_ENCODING_STATUS::OpenFailure);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(output);
|
||||
@@ -2258,6 +2343,9 @@ ScriptLoader::EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest)
|
||||
nsresult rv = output->Close();
|
||||
LOG(("ScriptLoadRequest (%p): Closing (rv = %X)",
|
||||
aRequest, unsigned(rv)));
|
||||
if (NS_FAILED(rv)) {
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_ENCODING_STATUS::CloseFailure);
|
||||
}
|
||||
});
|
||||
|
||||
uint32_t n;
|
||||
@@ -2266,11 +2354,13 @@ ScriptLoader::EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest)
|
||||
LOG(("ScriptLoadRequest (%p): Write bytecode cache (rv = %X, length = %u, written = %u)",
|
||||
aRequest, unsigned(rv), unsigned(aRequest->mScriptBytecode.length()), n));
|
||||
if (NS_FAILED(rv)) {
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_ENCODING_STATUS::WriteFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
bytecodeFailed.release();
|
||||
TRACE_FOR_TEST_NONE(aRequest->mElement, "scriptloader_bytecode_saved");
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_ENCODING_STATUS::EncodingSuccess);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2763,6 +2853,7 @@ ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
MOZ_ASSERT(aRequest->IsLoading());
|
||||
CollectScriptTelemetry(aLoader, aRequest);
|
||||
|
||||
// If we don't have a document, then we need to abort further
|
||||
// evaluation.
|
||||
|
||||
Reference in New Issue
Block a user