Skip to content

Commit abfd950

Browse files
fix: reduce memory usage
1 parent de02f7b commit abfd950

15 files changed

+2082
-1934
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"cacache": "^13.0.1",
4545
"find-cache-dir": "^3.2.0",
4646
"jest-worker": "^25.1.0",
47+
"p-limit": "^2.2.2",
4748
"schema-utils": "^2.6.4",
4849
"serialize-javascript": "^2.1.2",
4950
"source-map": "^0.6.1",

src/TaskRunner.js

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os from 'os';
22

3+
import pLimit from 'p-limit';
34
import Worker from 'jest-worker';
45
import serialize from 'serialize-javascript';
56

@@ -9,11 +10,15 @@ const workerPath = require.resolve('./worker');
910

1011
export default class TaskRunner {
1112
constructor(options = {}) {
13+
this.taskGenerator = options.taskGenerator;
14+
this.files = options.files;
1215
this.cache = options.cache;
13-
this.numberWorkers = TaskRunner.getNumberWorkers(options.parallel);
16+
this.availableNumberOfCores = TaskRunner.getAvailableNumberOfCores(
17+
options.parallel
18+
);
1419
}
1520

16-
static getNumberWorkers(parallel) {
21+
static getAvailableNumberOfCores(parallel) {
1722
// In some cases cpus() returns undefined
1823
// https://github.com/nodejs/node/issues/19022
1924
const cpus = os.cpus() || { length: 1 };
@@ -31,9 +36,18 @@ export default class TaskRunner {
3136
return minify(task);
3237
}
3338

34-
async run(tasks) {
35-
if (this.numberWorkers > 1) {
36-
this.worker = new Worker(workerPath, { numWorkers: this.numberWorkers });
39+
async run() {
40+
const { availableNumberOfCores, cache, files, taskGenerator } = this;
41+
42+
let concurrency = Infinity;
43+
44+
if (availableNumberOfCores > 0) {
45+
// Do not create unnecessary workers when the number of files is less than the available cores, it saves memory
46+
const numWorkers = Math.min(files.length, availableNumberOfCores);
47+
48+
concurrency = numWorkers;
49+
50+
this.worker = new Worker(workerPath, { numWorkers });
3751

3852
// Show syntax error from jest-worker
3953
// https://github.com/facebook/jest/issues/8872#issuecomment-524822081
@@ -44,34 +58,53 @@ export default class TaskRunner {
4458
}
4559
}
4660

47-
return Promise.all(
48-
tasks.map((task) => {
49-
const enqueue = async () => {
50-
let result;
61+
const limit = pLimit(concurrency);
62+
const scheduledTasks = [];
5163

52-
try {
53-
result = await this.runTask(task);
54-
} catch (error) {
55-
result = { error };
64+
for (const file of files) {
65+
const enqueue = async (task) => {
66+
let taskResult;
67+
68+
try {
69+
taskResult = await this.runTask(task);
70+
} catch (error) {
71+
taskResult = { error };
72+
}
73+
74+
if (cache.isEnabled() && !taskResult.error) {
75+
taskResult = await cache.store(task, taskResult).then(
76+
() => taskResult,
77+
() => taskResult
78+
);
79+
}
80+
81+
task.callback(taskResult);
82+
83+
return taskResult;
84+
};
85+
86+
scheduledTasks.push(
87+
limit(() => {
88+
const task = taskGenerator(file).next().value;
89+
90+
if (!task) {
91+
// Something went wrong, for example the `cacheKeys` option throw an error
92+
return Promise.resolve();
5693
}
5794

58-
if (this.cache.isEnabled() && !result.error) {
59-
return this.cache.store(task, result).then(
60-
() => result,
61-
() => result
95+
if (cache.isEnabled()) {
96+
return cache.get(task).then(
97+
(taskResult) => task.callback(taskResult),
98+
() => enqueue(task)
6299
);
63100
}
64101

65-
return result;
66-
};
67-
68-
if (this.cache.isEnabled()) {
69-
return this.cache.get(task).then((data) => data, enqueue);
70-
}
102+
return enqueue(task);
103+
})
104+
);
105+
}
71106

72-
return enqueue();
73-
})
74-
);
107+
return Promise.all(scheduledTasks);
75108
}
76109

77110
async exit() {

0 commit comments

Comments
 (0)