mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1656638: Add Wasm compile- and run-time telemetry to track Wasm compiler performance. r=lth
This patch adds telemetry to measure the time spent in Wasm compilers and in the code that they generate (actually, all JS and Wasm code). For simplicity, it measures wallclock time as a proxy for CPU time. Furthermore, it measures runtime for all JS and Wasm code, and all native functions invoked by the JS or Wasm code, by timing from top-level entry to exit. This is for efficiency reasons: we do not want to add a VM call in the transition stubs between native and JS or JS and Wasm; that would be a Very Bad Thing for performance, even for a Nightly build instrumented with telemetry. Because of that, it's difficult to separate JITted JS and JITted Wasm runtime, but observing their sum should still be useful when making comparisons across compiler changes because absolute reductions will still be visible. The plumbing is somewhat awkward, given that Wasm compilers can run on background threads. It appears that the telemetry-callback API that SpiderMonkey includes to avoid a direct dependency on the Gecko embedding had artificially limited the callback to main-thread use only. This patch removes that limitation, which is safe at least for Gecko; the telemetry hooks in Gecko are thread-safe (they take a global mutex). That way, the background threads performing compilation can directly add telemetry incrementally, without having to pass this up through the main thread somehow. Finally, I have chosen to add the relevant metrics as Scalar telemetry values rather than Histograms. This is because what we are really interested in is the sum of all these values (all CPU time spent in compilation + running Wasm code); if this value goes down as a result of a Wasm compiler change, then that Wasm compiler change is good because it reduces CPU time on the user's machine. It is difficult to add two Histograms together because the bins may have different boundaries. If we instead need to use a binned histogram for other reasons, then we could simply report the sum (of all compiler time plus run time) as another histogram. Differential Revision: https://phabricator.services.mozilla.com/D85654
This commit is contained in:
parent
96afc7c19e
commit
d53b8b620f
@ -481,6 +481,14 @@ js_option('--enable-cranelift',
|
||||
set_config('ENABLE_WASM_CRANELIFT', depends_if('--enable-cranelift')(lambda x: True))
|
||||
set_define('ENABLE_WASM_CRANELIFT', depends_if('--enable-cranelift')(lambda x: True))
|
||||
|
||||
# Telemetry to measure compile time and generated-code runtime
|
||||
# ============================================================
|
||||
|
||||
js_option('--enable-spidermonkey-telemetry',
|
||||
default=milestone.is_nightly,
|
||||
help='{Enable|Disable} performance telemetry for SpiderMonkey (e.g. compile and run times)')
|
||||
|
||||
set_define('ENABLE_SPIDERMONKEY_TELEMETRY', depends_if('--enable-spidermonkey-telemetry')(lambda x: True))
|
||||
|
||||
# Support for debugging code generated by wasm backends
|
||||
# =====================================================
|
||||
|
@ -59,6 +59,10 @@ enum {
|
||||
JS_TELEMETRY_GC_EFFECTIVENESS,
|
||||
JS_TELEMETRY_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS,
|
||||
JS_TELEMETRY_WEB_PARSER_COMPILE_LAZY_AFTER_MS,
|
||||
JS_TELEMETRY_RUN_TIME_US,
|
||||
JS_TELEMETRY_WASM_COMPILE_TIME_BASELINE_US,
|
||||
JS_TELEMETRY_WASM_COMPILE_TIME_ION_US,
|
||||
JS_TELEMETRY_WASM_COMPILE_TIME_CRANELIFT_US,
|
||||
JS_TELEMETRY_END
|
||||
};
|
||||
|
||||
|
@ -441,6 +441,15 @@ bool js::RunScript(JSContext* cx, RunState& state) {
|
||||
|
||||
GeckoProfilerEntryMarker marker(cx, state.script());
|
||||
|
||||
#ifdef ENABLE_SPIDERMONKEY_TELEMETRY
|
||||
bool measuringTime = !cx->isMeasuringExecutionTime();
|
||||
int64_t startTime = 0;
|
||||
if (measuringTime) {
|
||||
cx->setIsMeasuringExecutionTime(true);
|
||||
startTime = PRMJ_Now();
|
||||
}
|
||||
#endif
|
||||
|
||||
jit::EnterJitStatus status = jit::MaybeEnterJit(cx, state);
|
||||
switch (status) {
|
||||
case jit::EnterJitStatus::Error:
|
||||
@ -456,7 +465,18 @@ bool js::RunScript(JSContext* cx, RunState& state) {
|
||||
TypeMonitorCall(cx, invoke.args(), invoke.constructing());
|
||||
}
|
||||
|
||||
return Interpret(cx, state);
|
||||
bool ok = Interpret(cx, state);
|
||||
|
||||
#ifdef ENABLE_SPIDERMONKEY_TELEMETRY
|
||||
if (measuringTime) {
|
||||
int64_t endTime = PRMJ_Now();
|
||||
int64_t runtimeMicros = endTime - startTime;
|
||||
cx->runtime()->addTelemetry(JS_TELEMETRY_RUN_TIME_US, runtimeMicros);
|
||||
cx->setIsMeasuringExecutionTime(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ok;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
# pragma optimize("", on)
|
||||
|
@ -887,6 +887,7 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
|
||||
atomsZoneFreeLists_(this),
|
||||
defaultFreeOp_(this, runtime, true),
|
||||
freeUnusedMemory(false),
|
||||
measuringExecutionTime_(this, false),
|
||||
jitActivation(this, nullptr),
|
||||
isolate(this, nullptr),
|
||||
activation_(this, nullptr),
|
||||
|
@ -191,6 +191,10 @@ struct JS_PUBLIC_API JSContext : public JS::RootingContext,
|
||||
// free unused memory.
|
||||
mozilla::Atomic<bool, mozilla::ReleaseAcquire> freeUnusedMemory;
|
||||
|
||||
// Are we currently timing execution? This flag ensures that we do not
|
||||
// double-count execution time in reentrant situations.
|
||||
js::ContextData<bool> measuringExecutionTime_;
|
||||
|
||||
public:
|
||||
// This is used by helper threads to change the runtime their context is
|
||||
// currently operating on.
|
||||
@ -210,6 +214,11 @@ struct JS_PUBLIC_API JSContext : public JS::RootingContext,
|
||||
return kind_ == js::ContextKind::HelperThread && freeUnusedMemory;
|
||||
}
|
||||
|
||||
bool isMeasuringExecutionTime() const { return measuringExecutionTime_; }
|
||||
void setIsMeasuringExecutionTime(bool value) {
|
||||
measuringExecutionTime_ = value;
|
||||
}
|
||||
|
||||
bool isMainThreadContext() const {
|
||||
return kind_ == js::ContextKind::MainThread;
|
||||
}
|
||||
|
@ -318,6 +318,10 @@ void JSRuntime::addTelemetry(int id, uint32_t sample, const char* key) {
|
||||
}
|
||||
}
|
||||
|
||||
JSTelemetrySender JSRuntime::getTelemetrySender() const {
|
||||
return JSTelemetrySender(telemetryCallback);
|
||||
}
|
||||
|
||||
void JSRuntime::setTelemetryCallback(
|
||||
JSRuntime* rt, JSAccumulateTelemetryDataCallback callback) {
|
||||
rt->telemetryCallback = callback;
|
||||
|
@ -235,6 +235,8 @@ struct SelfHostedLazyScript {
|
||||
|
||||
} // namespace js
|
||||
|
||||
struct JSTelemetrySender;
|
||||
|
||||
struct JSRuntime {
|
||||
private:
|
||||
friend class js::Activation;
|
||||
@ -323,8 +325,9 @@ struct JSRuntime {
|
||||
profilerSampleBufferRangeStart_ = rangeStart;
|
||||
}
|
||||
|
||||
/* Call this to accumulate telemetry data. */
|
||||
js::MainThreadData<JSAccumulateTelemetryDataCallback> telemetryCallback;
|
||||
/* Call this to accumulate telemetry data. May be called from any thread; the
|
||||
* embedder is responsible for locking. */
|
||||
JSAccumulateTelemetryDataCallback telemetryCallback;
|
||||
|
||||
/* Call this to accumulate use counter data. */
|
||||
js::MainThreadData<JSSetUseCounterCallback> useCounterCallback;
|
||||
@ -337,6 +340,8 @@ struct JSRuntime {
|
||||
// |sample| is the data to add to the histogram.
|
||||
void addTelemetry(int id, uint32_t sample, const char* key = nullptr);
|
||||
|
||||
JSTelemetrySender getTelemetrySender() const;
|
||||
|
||||
void setTelemetryCallback(JSRuntime* rt,
|
||||
JSAccumulateTelemetryDataCallback callback);
|
||||
|
||||
@ -1071,6 +1076,34 @@ struct JSRuntime {
|
||||
#endif // defined(NIGHTLY_BUILD)
|
||||
};
|
||||
|
||||
// Context for sending telemetry to the embedder from any thread, main or
|
||||
// helper. Obtain a |JSTelemetrySender| by calling |getTelemetrySender()| on
|
||||
// the |JSRuntime|.
|
||||
struct JSTelemetrySender {
|
||||
private:
|
||||
friend struct JSRuntime;
|
||||
|
||||
JSAccumulateTelemetryDataCallback callback_;
|
||||
|
||||
explicit JSTelemetrySender(JSAccumulateTelemetryDataCallback callback)
|
||||
: callback_(callback) {}
|
||||
|
||||
public:
|
||||
JSTelemetrySender() : callback_(nullptr) {}
|
||||
JSTelemetrySender(const JSTelemetrySender& other) = default;
|
||||
explicit JSTelemetrySender(JSRuntime* runtime)
|
||||
: JSTelemetrySender(runtime->getTelemetrySender()) {}
|
||||
|
||||
// Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_*
|
||||
// histogram. |key| provides an additional key to identify the histogram.
|
||||
// |sample| is the data to add to the histogram.
|
||||
void addTelemetry(int id, uint32_t sample, const char* key = nullptr) {
|
||||
if (callback_) {
|
||||
callback_(id, sample, key);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
||||
static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Value* vec, size_t len) {
|
||||
|
@ -570,7 +570,8 @@ SharedModule wasm::CompileBuffer(const CompileArgs& args,
|
||||
const ShareableBytes& bytecode,
|
||||
UniqueChars* error,
|
||||
UniqueCharsVector* warnings,
|
||||
JS::OptimizedEncodingListener* listener) {
|
||||
JS::OptimizedEncodingListener* listener,
|
||||
JSTelemetrySender telemetrySender) {
|
||||
Decoder d(bytecode.bytes, 0, error, warnings);
|
||||
|
||||
CompilerEnvironment compilerEnv(args);
|
||||
@ -582,7 +583,7 @@ SharedModule wasm::CompileBuffer(const CompileArgs& args,
|
||||
}
|
||||
|
||||
ModuleGenerator mg(args, &env, nullptr, error);
|
||||
if (!mg.init()) {
|
||||
if (!mg.init(nullptr, telemetrySender)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -598,7 +599,8 @@ SharedModule wasm::CompileBuffer(const CompileArgs& args,
|
||||
}
|
||||
|
||||
void wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode,
|
||||
const Module& module, Atomic<bool>* cancelled) {
|
||||
const Module& module, Atomic<bool>* cancelled,
|
||||
JSTelemetrySender telemetrySender) {
|
||||
UniqueChars error;
|
||||
Decoder d(bytecode, 0, &error);
|
||||
|
||||
@ -628,7 +630,7 @@ void wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode,
|
||||
}
|
||||
|
||||
ModuleGenerator mg(args, &env, cancelled, &error);
|
||||
if (!mg.init()) {
|
||||
if (!mg.init(nullptr, telemetrySender)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -728,7 +730,7 @@ SharedModule wasm::CompileStreaming(
|
||||
const ExclusiveBytesPtr& codeBytesEnd,
|
||||
const ExclusiveStreamEndData& exclusiveStreamEnd,
|
||||
const Atomic<bool>& cancelled, UniqueChars* error,
|
||||
UniqueCharsVector* warnings) {
|
||||
UniqueCharsVector* warnings, JSTelemetrySender telemetrySender) {
|
||||
CompilerEnvironment compilerEnv(args);
|
||||
ModuleEnvironment env(&compilerEnv, args.sharedMemoryEnabled
|
||||
? Shareable::True
|
||||
@ -751,7 +753,7 @@ SharedModule wasm::CompileStreaming(
|
||||
}
|
||||
|
||||
ModuleGenerator mg(args, &env, &cancelled, error);
|
||||
if (!mg.init()) {
|
||||
if (!mg.init(nullptr, telemetrySender)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -100,15 +100,17 @@ double EstimateCompiledCodeSize(Tier tier, size_t bytecodeSize);
|
||||
// - *error points to a string description of the error
|
||||
// - *error is null and the caller should report out-of-memory.
|
||||
|
||||
SharedModule CompileBuffer(const CompileArgs& args,
|
||||
const ShareableBytes& bytecode, UniqueChars* error,
|
||||
UniqueCharsVector* warnings,
|
||||
JS::OptimizedEncodingListener* listener = nullptr);
|
||||
SharedModule CompileBuffer(
|
||||
const CompileArgs& args, const ShareableBytes& bytecode, UniqueChars* error,
|
||||
UniqueCharsVector* warnings,
|
||||
JS::OptimizedEncodingListener* listener = nullptr,
|
||||
JSTelemetrySender telemetrySender = JSTelemetrySender());
|
||||
|
||||
// Attempt to compile the second tier of the given wasm::Module.
|
||||
|
||||
void CompileTier2(const CompileArgs& args, const Bytes& bytecode,
|
||||
const Module& module, Atomic<bool>* cancelled);
|
||||
const Module& module, Atomic<bool>* cancelled,
|
||||
JSTelemetrySender telemetrySender = JSTelemetrySender());
|
||||
|
||||
// Compile the given WebAssembly module which has been broken into three
|
||||
// partitions:
|
||||
@ -139,12 +141,12 @@ struct StreamEndData {
|
||||
};
|
||||
using ExclusiveStreamEndData = ExclusiveWaitableData<StreamEndData>;
|
||||
|
||||
SharedModule CompileStreaming(const CompileArgs& args, const Bytes& envBytes,
|
||||
const Bytes& codeBytes,
|
||||
const ExclusiveBytesPtr& codeBytesEnd,
|
||||
const ExclusiveStreamEndData& streamEnd,
|
||||
const Atomic<bool>& cancelled, UniqueChars* error,
|
||||
UniqueCharsVector* warnings);
|
||||
SharedModule CompileStreaming(
|
||||
const CompileArgs& args, const Bytes& envBytes, const Bytes& codeBytes,
|
||||
const ExclusiveBytesPtr& codeBytesEnd,
|
||||
const ExclusiveStreamEndData& streamEnd, const Atomic<bool>& cancelled,
|
||||
UniqueChars* error, UniqueCharsVector* warnings,
|
||||
JSTelemetrySender telemetrySender = JSTelemetrySender());
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace js
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "util/Memory.h"
|
||||
#include "util/Text.h"
|
||||
#include "vm/Time.h"
|
||||
#include "wasm/WasmBaselineCompile.h"
|
||||
#include "wasm/WasmCompile.h"
|
||||
#include "wasm/WasmCraneliftCompile.h"
|
||||
@ -169,9 +170,12 @@ bool ModuleGenerator::allocateGlobalBytes(uint32_t bytes, uint32_t align,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ModuleGenerator::init(Metadata* maybeAsmJSMetadata) {
|
||||
bool ModuleGenerator::init(Metadata* maybeAsmJSMetadata,
|
||||
JSTelemetrySender telemetrySender) {
|
||||
// Perform fallible metadata, linkdata, assumption allocations.
|
||||
|
||||
telemetrySender_ = telemetrySender;
|
||||
|
||||
MOZ_ASSERT(isAsmJS() == !!maybeAsmJSMetadata);
|
||||
if (maybeAsmJSMetadata) {
|
||||
metadata_ = maybeAsmJSMetadata;
|
||||
@ -439,7 +443,8 @@ bool ModuleGenerator::init(Metadata* maybeAsmJSMetadata) {
|
||||
}
|
||||
for (size_t i = 0; i < numTasks; i++) {
|
||||
tasks_.infallibleEmplaceBack(*env_, taskState_,
|
||||
COMPILATION_LIFO_DEFAULT_CHUNK_SIZE);
|
||||
COMPILATION_LIFO_DEFAULT_CHUNK_SIZE,
|
||||
telemetrySender);
|
||||
}
|
||||
|
||||
if (!freeTasks_.reserve(numTasks)) {
|
||||
@ -736,6 +741,11 @@ static bool ExecuteCompileTask(CompileTask* task, UniqueChars* error) {
|
||||
MOZ_ASSERT(task->lifo.isEmpty());
|
||||
MOZ_ASSERT(task->output.empty());
|
||||
|
||||
#ifdef ENABLE_SPIDERMONKEY_TELEMETRY
|
||||
int64_t startTime = PRMJ_Now();
|
||||
int compileTimeTelemetryID;
|
||||
#endif
|
||||
|
||||
switch (task->env.tier()) {
|
||||
case Tier::Optimized:
|
||||
switch (task->env.optimizedBackend()) {
|
||||
@ -744,12 +754,18 @@ static bool ExecuteCompileTask(CompileTask* task, UniqueChars* error) {
|
||||
&task->output, error)) {
|
||||
return false;
|
||||
}
|
||||
#ifdef ENABLE_SPIDERMONKEY_TELEMETRY
|
||||
compileTimeTelemetryID = JS_TELEMETRY_WASM_COMPILE_TIME_CRANELIFT_US;
|
||||
#endif
|
||||
break;
|
||||
case OptimizedBackend::Ion:
|
||||
if (!IonCompileFunctions(task->env, task->lifo, task->inputs,
|
||||
&task->output, error)) {
|
||||
return false;
|
||||
}
|
||||
#ifdef ENABLE_SPIDERMONKEY_TELEMETRY
|
||||
compileTimeTelemetryID = JS_TELEMETRY_WASM_COMPILE_TIME_ION_US;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -758,9 +774,19 @@ static bool ExecuteCompileTask(CompileTask* task, UniqueChars* error) {
|
||||
&task->output, error)) {
|
||||
return false;
|
||||
}
|
||||
#ifdef ENABLE_SPIDERMONKEY_TELEMETRY
|
||||
compileTimeTelemetryID = JS_TELEMETRY_WASM_COMPILE_TIME_BASELINE_US;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SPIDERMONKEY_TELEMETRY
|
||||
int64_t endTime = PRMJ_Now();
|
||||
int64_t compileTimeMicros = endTime - startTime;
|
||||
|
||||
task->telemetrySender.addTelemetry(compileTimeTelemetryID, compileTimeMicros);
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT(task->lifo.isEmpty());
|
||||
MOZ_ASSERT(task->inputs.length() == task->output.codeRanges.length());
|
||||
task->inputs.clear();
|
||||
@ -1257,7 +1283,8 @@ SharedModule ModuleGenerator::finishModule(
|
||||
}
|
||||
|
||||
if (mode() == CompileMode::Tier1) {
|
||||
module->startTier2(*compileArgs_, bytecode, maybeTier2Listener);
|
||||
module->startTier2(*compileArgs_, bytecode, maybeTier2Listener,
|
||||
telemetrySender_);
|
||||
} else if (tier() == Tier::Serialized && maybeTier2Listener) {
|
||||
module->serialize(*linkData_, *maybeTier2Listener);
|
||||
}
|
||||
|
@ -130,10 +130,14 @@ struct CompileTask : public RunnableTask {
|
||||
LifoAlloc lifo;
|
||||
FuncCompileInputVector inputs;
|
||||
CompiledCode output;
|
||||
JSTelemetrySender telemetrySender;
|
||||
|
||||
CompileTask(const ModuleEnvironment& env, ExclusiveCompileTaskState& state,
|
||||
size_t defaultChunkSize)
|
||||
: env(env), state(state), lifo(defaultChunkSize) {}
|
||||
size_t defaultChunkSize, JSTelemetrySender telemetrySender)
|
||||
: env(env),
|
||||
state(state),
|
||||
lifo(defaultChunkSize),
|
||||
telemetrySender(telemetrySender) {}
|
||||
|
||||
virtual ~CompileTask() = default;
|
||||
|
||||
@ -164,6 +168,7 @@ class MOZ_STACK_CLASS ModuleGenerator {
|
||||
UniqueChars* const error_;
|
||||
const Atomic<bool>* const cancelled_;
|
||||
ModuleEnvironment* const env_;
|
||||
JSTelemetrySender telemetrySender_;
|
||||
|
||||
// Data that is moved into the result of finish()
|
||||
UniqueLinkData linkData_;
|
||||
@ -221,7 +226,9 @@ class MOZ_STACK_CLASS ModuleGenerator {
|
||||
ModuleGenerator(const CompileArgs& args, ModuleEnvironment* env,
|
||||
const Atomic<bool>* cancelled, UniqueChars* error);
|
||||
~ModuleGenerator();
|
||||
MOZ_MUST_USE bool init(Metadata* maybeAsmJSMetadata = nullptr);
|
||||
MOZ_MUST_USE bool init(
|
||||
Metadata* maybeAsmJSMetadata = nullptr,
|
||||
JSTelemetrySender telemetrySender = JSTelemetrySender());
|
||||
|
||||
// Before finishFuncDefs() is called, compileFuncDef() must be called once
|
||||
// for each funcIndex in the range [0, env->numFuncDefs()).
|
||||
|
@ -775,8 +775,9 @@ bool wasm::Eval(JSContext* cx, Handle<TypedArrayObject*> code,
|
||||
|
||||
UniqueChars error;
|
||||
UniqueCharsVector warnings;
|
||||
SharedModule module =
|
||||
CompileBuffer(*compileArgs, *bytecode, &error, &warnings);
|
||||
JSTelemetrySender sender(cx->runtime());
|
||||
SharedModule module = CompileBuffer(*compileArgs, *bytecode, &error,
|
||||
&warnings, nullptr, sender);
|
||||
if (!module) {
|
||||
if (error) {
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||
@ -1518,8 +1519,9 @@ bool WasmModuleObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
UniqueChars error;
|
||||
UniqueCharsVector warnings;
|
||||
SharedModule module =
|
||||
CompileBuffer(*compileArgs, *bytecode, &error, &warnings);
|
||||
JSTelemetrySender sender(cx->runtime());
|
||||
SharedModule module = CompileBuffer(*compileArgs, *bytecode, &error,
|
||||
&warnings, nullptr, sender);
|
||||
if (!module) {
|
||||
if (error) {
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||
@ -3464,12 +3466,14 @@ struct CompileBufferTask : PromiseHelperTask {
|
||||
SharedModule module;
|
||||
bool instantiate;
|
||||
PersistentRootedObject importObj;
|
||||
JSTelemetrySender sender;
|
||||
|
||||
CompileBufferTask(JSContext* cx, Handle<PromiseObject*> promise,
|
||||
HandleObject importObj)
|
||||
: PromiseHelperTask(cx, promise),
|
||||
instantiate(true),
|
||||
importObj(cx, importObj) {}
|
||||
importObj(cx, importObj),
|
||||
sender(cx->runtime()) {}
|
||||
|
||||
CompileBufferTask(JSContext* cx, Handle<PromiseObject*> promise)
|
||||
: PromiseHelperTask(cx, promise), instantiate(false) {}
|
||||
@ -3483,7 +3487,8 @@ struct CompileBufferTask : PromiseHelperTask {
|
||||
}
|
||||
|
||||
void execute() override {
|
||||
module = CompileBuffer(*compileArgs, *bytecode, &error, &warnings);
|
||||
module = CompileBuffer(*compileArgs, *bytecode, &error, &warnings, nullptr,
|
||||
sender);
|
||||
}
|
||||
|
||||
bool resolve(JSContext* cx, Handle<PromiseObject*> promise) override {
|
||||
@ -3732,6 +3737,8 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer {
|
||||
// Set on stream thread and read racily on helper thread to abort compilation:
|
||||
Atomic<bool> streamFailed_;
|
||||
|
||||
JSTelemetrySender sender_;
|
||||
|
||||
// Called on some thread before consumeChunk(), streamEnd(), streamError()):
|
||||
|
||||
void noteResponseURLs(const char* url, const char* sourceMapUrl) override {
|
||||
@ -3877,8 +3884,8 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer {
|
||||
rejectAndDestroyBeforeHelperThreadStarted(StreamOOMCode);
|
||||
return;
|
||||
}
|
||||
module_ =
|
||||
CompileBuffer(*compileArgs_, *bytecode, &compileError_, &warnings_);
|
||||
module_ = CompileBuffer(*compileArgs_, *bytecode, &compileError_,
|
||||
&warnings_, nullptr, sender_);
|
||||
setClosedAndDestroyBeforeHelperThreadStarted();
|
||||
return;
|
||||
}
|
||||
@ -3925,9 +3932,10 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer {
|
||||
// Called on a helper thread:
|
||||
|
||||
void execute() override {
|
||||
module_ = CompileStreaming(*compileArgs_, envBytes_, codeBytes_,
|
||||
exclusiveCodeBytesEnd_, exclusiveStreamEnd_,
|
||||
streamFailed_, &compileError_, &warnings_);
|
||||
module_ =
|
||||
CompileStreaming(*compileArgs_, envBytes_, codeBytes_,
|
||||
exclusiveCodeBytesEnd_, exclusiveStreamEnd_,
|
||||
streamFailed_, &compileError_, &warnings_, sender_);
|
||||
|
||||
// When execute() returns, the CompileStreamTask will be dispatched
|
||||
// back to its JS thread to call resolve() and then be destroyed. We
|
||||
@ -3975,7 +3983,8 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer {
|
||||
codeBytesEnd_(nullptr),
|
||||
exclusiveCodeBytesEnd_(mutexid::WasmCodeBytesEnd, nullptr),
|
||||
exclusiveStreamEnd_(mutexid::WasmStreamEnd),
|
||||
streamFailed_(false) {
|
||||
streamFailed_(false),
|
||||
sender_(cx->runtime()) {
|
||||
MOZ_ASSERT_IF(importObj_, instantiate_);
|
||||
}
|
||||
};
|
||||
|
@ -48,14 +48,17 @@ class Module::Tier2GeneratorTaskImpl : public Tier2GeneratorTask {
|
||||
SharedBytes bytecode_;
|
||||
SharedModule module_;
|
||||
Atomic<bool> cancelled_;
|
||||
JSTelemetrySender telemetrySender_;
|
||||
|
||||
public:
|
||||
Tier2GeneratorTaskImpl(const CompileArgs& compileArgs,
|
||||
const ShareableBytes& bytecode, Module& module)
|
||||
const ShareableBytes& bytecode, Module& module,
|
||||
JSTelemetrySender telemetrySender)
|
||||
: compileArgs_(&compileArgs),
|
||||
bytecode_(&bytecode),
|
||||
module_(&module),
|
||||
cancelled_(false) {}
|
||||
cancelled_(false),
|
||||
telemetrySender_(telemetrySender) {}
|
||||
|
||||
~Tier2GeneratorTaskImpl() override {
|
||||
module_->tier2Listener_ = nullptr;
|
||||
@ -80,7 +83,8 @@ class Module::Tier2GeneratorTaskImpl : public Tier2GeneratorTask {
|
||||
}
|
||||
|
||||
void runTask() {
|
||||
CompileTier2(*compileArgs_, bytecode_->bytes, *module_, &cancelled_);
|
||||
CompileTier2(*compileArgs_, bytecode_->bytes, *module_, &cancelled_,
|
||||
telemetrySender_);
|
||||
}
|
||||
ThreadType threadType() override {
|
||||
return ThreadType::THREAD_TYPE_WASM_TIER2;
|
||||
@ -94,10 +98,12 @@ Module::~Module() {
|
||||
}
|
||||
|
||||
void Module::startTier2(const CompileArgs& args, const ShareableBytes& bytecode,
|
||||
JS::OptimizedEncodingListener* listener) {
|
||||
JS::OptimizedEncodingListener* listener,
|
||||
JSTelemetrySender telemetrySender) {
|
||||
MOZ_ASSERT(!testingTier2Active_);
|
||||
|
||||
auto task = MakeUnique<Tier2GeneratorTaskImpl>(args, bytecode, *this);
|
||||
auto task = MakeUnique<Tier2GeneratorTaskImpl>(args, bytecode, *this,
|
||||
telemetrySender);
|
||||
if (!task) {
|
||||
return;
|
||||
}
|
||||
|
@ -192,7 +192,8 @@ class Module : public JS::WasmModule {
|
||||
// be installed and made visible.
|
||||
|
||||
void startTier2(const CompileArgs& args, const ShareableBytes& bytecode,
|
||||
JS::OptimizedEncodingListener* listener);
|
||||
JS::OptimizedEncodingListener* listener,
|
||||
JSTelemetrySender telemetrySender);
|
||||
bool finishTier2(const LinkData& linkData2, UniqueCodeTier code2) const;
|
||||
|
||||
void testingBlockOnTier2Complete() const;
|
||||
|
@ -2648,6 +2648,21 @@ static void AccumulateTelemetryCallback(int id, uint32_t sample,
|
||||
Telemetry::Accumulate(Telemetry::JS_WEB_PARSER_COMPILE_LAZY_AFTER_MS,
|
||||
sample);
|
||||
break;
|
||||
case JS_TELEMETRY_RUN_TIME_US:
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::JS_RUN_TIME_US, sample);
|
||||
break;
|
||||
case JS_TELEMETRY_WASM_COMPILE_TIME_BASELINE_US:
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::WASM_COMPILE_TIME_BASELINE_US,
|
||||
sample);
|
||||
break;
|
||||
case JS_TELEMETRY_WASM_COMPILE_TIME_ION_US:
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::WASM_COMPILE_TIME_ION_US,
|
||||
sample);
|
||||
break;
|
||||
case JS_TELEMETRY_WASM_COMPILE_TIME_CRANELIFT_US:
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::WASM_COMPILE_TIME_CRANELIFT_US,
|
||||
sample);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected JS_TELEMETRY id");
|
||||
}
|
||||
|
@ -4586,6 +4586,84 @@ script.preloader:
|
||||
- 'main'
|
||||
- 'content'
|
||||
|
||||
wasm:
|
||||
compile_time_baseline_us:
|
||||
bug_numbers:
|
||||
- 1656638
|
||||
description:
|
||||
How many microseconds we spent in the baseline WebAssembly compiler.
|
||||
expires: "88"
|
||||
keyed: false
|
||||
kind: uint
|
||||
notification_emails:
|
||||
- cfallin@mozilla.com
|
||||
- bbouvier@mozilla.com
|
||||
- jseward@mozilla.com
|
||||
release_channel_collection: opt-in
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
- 'content'
|
||||
|
||||
compile_time_cranelift_us:
|
||||
bug_numbers:
|
||||
- 1656638
|
||||
description:
|
||||
How many microseconds we spent in the Cranelift WebAssembly compiler.
|
||||
expires: "88"
|
||||
keyed: false
|
||||
kind: uint
|
||||
notification_emails:
|
||||
- cfallin@mozilla.com
|
||||
- bbouvier@mozilla.com
|
||||
- jseward@mozilla.com
|
||||
release_channel_collection: opt-in
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
compile_time_ion_us:
|
||||
bug_numbers:
|
||||
- 1656638
|
||||
description:
|
||||
How many microseconds we spent in the IonMonkey WebAssembly compiler.
|
||||
expires: "88"
|
||||
keyed: false
|
||||
kind: uint
|
||||
notification_emails:
|
||||
- cfallin@mozilla.com
|
||||
- bbouvier@mozilla.com
|
||||
- jseward@mozilla.com
|
||||
release_channel_collection: opt-in
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
- 'content'
|
||||
|
||||
js:
|
||||
run_time_us:
|
||||
bug_numbers:
|
||||
- 1656638
|
||||
description:
|
||||
How many microseconds we spent in running user code in SpiderMonkey,
|
||||
including JavaScript code and WebAssembly code.
|
||||
expires: "88"
|
||||
keyed: false
|
||||
kind: uint
|
||||
notification_emails:
|
||||
- cfallin@mozilla.com
|
||||
- bbouvier@mozilla.com
|
||||
- jseward@mozilla.com
|
||||
release_channel_collection: opt-in
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
- 'content'
|
||||
|
||||
networking:
|
||||
nss_initialization:
|
||||
bug_numbers:
|
||||
|
Loading…
Reference in New Issue
Block a user