Skip to content

Commit

Permalink
attemptGarbageCollection periodically (every N subcases) (#4007)
Browse files Browse the repository at this point in the history
  • Loading branch information
kainino0x authored Oct 18, 2024
1 parent ecefa0d commit da76b20
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 117 deletions.
13 changes: 13 additions & 0 deletions src/common/framework/test_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,20 @@ export type TestConfig = {
*/
enableDebugLogs: boolean;

/**
* Maximum number of subcases in flight at once, within a case. Once this many
* are in flight, wait for a subcase to finish before starting the next one.
*/
maxSubcasesInFlight: number;

/**
* Every `subcasesBetweenAttemptingGC` subcases, run `attemptGarbageCollection()`.
* Setting to `Infinity` disables this. Setting to 1 attempts GC every time (slow!).
*/
subcasesBetweenAttemptingGC: number;

testHeartbeatCallback: () => void;

noRaceWithRejectOnTimeout: boolean;

/**
Expand Down Expand Up @@ -41,6 +53,7 @@ export type TestConfig = {
export const globalTestConfig: TestConfig = {
enableDebugLogs: false,
maxSubcasesInFlight: 100,
subcasesBetweenAttemptingGC: 5000,
testHeartbeatCallback: () => {},
noRaceWithRejectOnTimeout: false,
unrollConstEvalLoops: false,
Expand Down
34 changes: 27 additions & 7 deletions src/common/internal/test_group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
stringifyPublicParamsUniquely,
} from '../internal/query/stringify_params.js';
import { validQueryPart } from '../internal/query/validQueryPart.js';
import { attemptGarbageCollection } from '../util/collect_garbage.js';
import { DeepReadonly } from '../util/types.js';
import { assert, unreachable } from '../util/util.js';

Expand Down Expand Up @@ -696,6 +697,7 @@ class RunCaseSpecific implements RunCase {
subRec.threw(ex);
}
})
.finally(attemptGarbageCollectionIfDue)
.finally(subcaseFinishedCallback);

allPreviousSubcasesFinalizedPromise = allPreviousSubcasesFinalizedPromise.then(
Expand All @@ -711,13 +713,17 @@ class RunCaseSpecific implements RunCase {
rec.skipped(new SkipTestCase('all subcases were skipped'));
}
} else {
await this.runTest(
rec,
sharedState,
this.params,
/* throwSkip */ false,
getExpectedStatus(selfQuery)
);
try {
await this.runTest(
rec,
sharedState,
this.params,
/* throwSkip */ false,
getExpectedStatus(selfQuery)
);
} finally {
await attemptGarbageCollectionIfDue();
}
}
} finally {
testHeartbeatCallback();
Expand Down Expand Up @@ -754,3 +760,17 @@ export type CaseTimingLogLine = {
*/
nonskippedSubcaseCount: number;
};

/** Every `subcasesBetweenAttemptingGC` calls to this function will `attemptGarbageCollection()`. */
const attemptGarbageCollectionIfDue: () => Promise<void> = (() => {
// This state is global because garbage is global.
let subcasesSinceLastGC = 0;

return async function attemptGarbageCollectionIfDue() {
subcasesSinceLastGC++;
if (subcasesSinceLastGC >= globalTestConfig.subcasesBetweenAttemptingGC) {
subcasesSinceLastGC = 0;
return attemptGarbageCollection();
}
};
})();
220 changes: 110 additions & 110 deletions src/resources/cache/hashes.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit da76b20

Please sign in to comment.