@samitouri / QOS-React-2 / commits / c84b817972

[be][snap] Warm up workers when in watch + filter mode

Mofei Zhang committed Mar 11, 2024 at 13:55 UTC c84b81797298cccc95e653ba7387063ceee7268a
2 files changed +45 -21
compiler/packages/snap/src/runner-watch.ts
+15 -21
@@ -114,7 +114,6 @@ function subscribeFixtures(
114 onChange: (state: RunnerState) => void
115 ) {
116 // Watch the fixtures directory for changes
117 - /* const fileSubscription = */
117 watcher.subscribe(FIXTURES_PATH, async (err, _events) => {
118 if (err) {
119 console.error(err);
@@ -127,6 +126,7 @@ function subscribeFixtures(
126 const isRealUpdate = performance.now() - state.lastUpdate > 5000;
127 if (isRealUpdate) {
128 // Fixtures changed, re-run tests
129 + state.mode.action = RunnerAction.Test;
130 onChange(state);
131 }
132 });
@@ -136,23 +136,20 @@ function subscribeFilterFile(
136 state: RunnerState,
137 onChange: (state: RunnerState) => void
138 ) {
139 - const filterSubscription = watcher.subscribe(
140 - process.cwd(),
141 - async (err, events) => {
142 - if (err) {
143 - console.error(err);
144 - process.exit(1);
145 - } else if (
146 - events.findIndex((event) => event.path.includes(FILTER_FILENAME)) !== -1
147 - ) {
148 - state.filter = await readTestFilter();
149 - if (state.mode.filter) {
150 - state.mode.action = RunnerAction.Test;
151 - onChange(state);
152 - }
139 + watcher.subscribe(process.cwd(), async (err, events) => {
140 + if (err) {
141 + console.error(err);
142 + process.exit(1);
143 + } else if (
144 + events.findIndex((event) => event.path.includes(FILTER_FILENAME)) !== -1
145 + ) {
146 + state.filter = await readTestFilter();
147 + if (state.mode.filter) {
148 + state.mode.action = RunnerAction.Test;
149 + onChange(state);
150 }
151 }
155 - );
152 + });
153 }
154
155 function subscribeTsc(
@@ -172,11 +169,7 @@ function subscribeTsc(
169 state.compilerVersion++;
170 }
171 state.isCompilerBuildValid = isSuccess;
175 - if (state.filter) {
176 - state.mode.action = RunnerAction.Test;
177 - } else {
178 - state.mode.action = RunnerAction.Test;
179 - }
172 + state.mode.action = RunnerAction.Test;
173 onChange(state);
174 }
175 );
@@ -194,6 +187,7 @@ function subscribeKeyEvents(
187 process.exit(0);
188 } else if (key.name === "f") {
189 state.mode.filter = !state.mode.filter;
190 + state.mode.action = RunnerAction.Test;
191 } else {
192 // any other key re-runs tests
193 state.mode.action = RunnerAction.Test;
compiler/packages/snap/src/runner.ts
+30
@@ -6,6 +6,7 @@
6 */
7
8 import { Worker } from "jest-worker";
9 +import { cpus } from "os";
10 import process from "process";
11 import * as readline from "readline";
12 import ts from "typescript";
@@ -23,6 +24,7 @@ import {
24 import * as runnerWorker from "./runner-worker";
25
26 const WORKER_PATH = require.resolve("./runner-worker.js");
27 +const NUM_WORKERS = cpus().length - 1;
28
29 readline.emitKeypressEvents(process.stdin);
30
@@ -163,12 +165,40 @@ async function onChange(
165 export async function main(opts: RunnerOptions): Promise<void> {
166 const worker: Worker & typeof runnerWorker = new Worker(WORKER_PATH, {
167 enableWorkerThreads: opts.workerThreads,
168 + numWorkers: NUM_WORKERS,
169 }) as any;
170 worker.getStderr().pipe(process.stderr);
171 worker.getStdout().pipe(process.stdout);
172
173 if (opts.watch) {
174 makeWatchRunner((state) => onChange(worker, state), opts.filter);
175 + if (opts.filter) {
176 + /**
177 + * Warm up wormers when in watch mode. Loading the Forget babel plugin
178 + * and all of its transitive dependencies takes 1-3s (per worker) on a M1.
179 + * As jest-worker dispatches tasks using a round-robin strategy, we can
180 + * avoid an additional 1-3s wait on the first num_workers runs by warming
181 + * up workers eagerly.
182 + */
183 + for (let i = 0; i < NUM_WORKERS - 1; i++) {
184 + worker.transformFixture(
185 + {
186 + fixturePath: "tmp",
187 + snapshotPath: "./tmp.expect.md",
188 + inputPath: "./tmp.js",
189 + input: `
190 + function Foo(props) {
191 + return identity(props);
192 + }
193 + `,
194 + snapshot: null,
195 + },
196 + 0,
197 + false,
198 + false
199 + );
200 + }
201 + }
202 } else {
203 // Non-watch mode. For simplicity we re-use the same watchSrc() function.
204 // After the first build completes run tests and exit