From 075b66b62a13435c9c04e28f11db3dcee9a94c21 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Mon, 6 Jan 2020 18:19:28 +0000 Subject: [PATCH] Bug 1607259 - Allow configuring the maximum number of running processes, r=jlast. Differential Revision: https://phabricator.services.mozilla.com/D58817 --HG-- extra : moz-landing-system : lando --- devtools/server/actors/replay/control.js | 17 ++++++++++------- devtools/server/actors/replay/replay.js | 6 +++--- toolkit/recordreplay/ipc/JSControl.cpp | 23 +++++++++++++++++++++++ 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/devtools/server/actors/replay/control.js b/devtools/server/actors/replay/control.js index ed1fb81d0201..92c317e631a1 100644 --- a/devtools/server/actors/replay/control.js +++ b/devtools/server/actors/replay/control.js @@ -150,14 +150,17 @@ function ChildProcess(rootId, forkId, recording, recordingLength, startPoint) { // run forward to the first checkpoint. this.manifests = [ { - manifest: { kind: "initial" }, - onFinished: ({ point }) => { + manifest: { kind: "primordial" }, + onFinished: ({ point, maxRunningProcesses }) => { if (this == gMainChild) { getCheckpointInfo(FirstCheckpointId).point = point; Services.tm.dispatchToMainThread( recording ? maybeResumeRecording : setMainChild ); } + if (maxRunningProcesses) { + gMaxRunningLeafChildren = maxRunningProcesses; + } }, }, ]; @@ -477,7 +480,7 @@ function newLeafChild(endpoint, onFinished = () => {}) { } // How many leaf children we can have running simultaneously. -const MaxRunningLeafChildren = 4; +let gMaxRunningLeafChildren = 4; // How many leaf children are currently running. let gNumRunningLeafChildren = 0; @@ -489,7 +492,7 @@ const gChildWaiters = [[], [], []]; // the limits on the maximum number of running leaves and returning the new // child when it reaches the endpoint. async function ensureLeafChild(endpoint, priority = Priority.HIGH) { - if (gNumRunningLeafChildren < MaxRunningLeafChildren) { + if (gNumRunningLeafChildren < gMaxRunningLeafChildren) { gNumRunningLeafChildren++; } else { await new Promise(resolve => gChildWaiters[priority].push(resolve)); @@ -505,7 +508,7 @@ async function ensureLeafChild(endpoint, priority = Priority.HIGH) { function stopRunningLeafChild() { gNumRunningLeafChildren--; - if (gNumRunningLeafChildren < MaxRunningLeafChildren) { + if (gNumRunningLeafChildren < gMaxRunningLeafChildren) { for (const waiters of gChildWaiters) { if (waiters.length) { const resolve = waiters.shift(); @@ -617,14 +620,14 @@ function respawnCrashedChild(child) { } for (const manifest of processedManifests) { - if (manifest.kind != "initial" && manifest.kind != "fork") { + if (manifest.kind != "primordial" && manifest.kind != "fork") { child.sendManifest(manifest); } } for (const { manifest, onFinished } of manifests) { if ( - manifest.kind != "initial" && + manifest.kind != "primordial" && (manifest.kind != "fork" || manifest != manifests[0].manifest) ) { child.sendManifest(manifest, onFinished); diff --git a/devtools/server/actors/replay/replay.js b/devtools/server/actors/replay/replay.js index a5c43a71d397..acefbaca84b8 100644 --- a/devtools/server/actors/replay/replay.js +++ b/devtools/server/actors/replay/replay.js @@ -1132,10 +1132,10 @@ function finishResume(point) { // finished. This does not need to be specified for all manifests. const gManifestFinishedAfterCheckpointHandlers = { primordial(_, point) { - // The primordial manifest runs forward to the first checkpoint, saves it, - // and then finishes. + // The primordial manifest runs forward to the first checkpoint. assert(point.checkpoint == FirstCheckpointId); - RecordReplayControl.manifestFinished({ point }); + const maxRunningProcesses = RecordReplayControl.maxRunningProcesses(); + RecordReplayControl.manifestFinished({ point, maxRunningProcesses }); }, resume(_, point) { diff --git a/toolkit/recordreplay/ipc/JSControl.cpp b/toolkit/recordreplay/ipc/JSControl.cpp index 5bdc43355288..6b041eda4991 100644 --- a/toolkit/recordreplay/ipc/JSControl.cpp +++ b/toolkit/recordreplay/ipc/JSControl.cpp @@ -996,6 +996,28 @@ static bool RecordReplay_Repaint(JSContext* aCx, unsigned aArgc, Value* aVp) { return true; } +static bool RecordReplay_MaxRunningProcesses(JSContext* aCx, unsigned aArgc, + Value* aVp) { + CallArgs args = CallArgsFromVp(aArgc, aVp); + args.rval().setUndefined(); + + // The number of processes we can run at a time is supplied via an environment + // variable. This is normally set by the translation layer when we are running + // in the cloud. + if (IsReplaying()) { + AutoEnsurePassThroughThreadEvents pt; + const char* env = getenv("MOZ_REPLAYING_MAX_RUNNING_PROCESSES"); + if (env) { + int numProcesses = atoi(env); + if (numProcesses > 0) { + args.rval().setInt32(numProcesses); + } + } + } + + return true; +} + static bool RecordReplay_Dump(JSContext* aCx, unsigned aArgc, Value* aVp) { // This method is an alternative to dump() that can be used in places where // thread events are disallowed. @@ -1479,6 +1501,7 @@ static const JSFunctionSpec gRecordReplayMethods[] = { 0), JS_FN("findScriptHits", RecordReplay_FindScriptHits, 3, 0), JS_FN("findChangeFrames", RecordReplay_FindChangeFrames, 3, 0), + JS_FN("maxRunningProcesses", RecordReplay_MaxRunningProcesses, 0, 0), JS_FN("dump", RecordReplay_Dump, 1, 0), JS_FS_END};