-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cache checked files in fs #8388
Cache checked files in fs #8388
Conversation
Codecov Report
@@ Coverage Diff @@
## master #8388 +/- ##
==========================================
+ Coverage 62.34% 62.37% +0.02%
==========================================
Files 266 266
Lines 10734 10739 +5
Branches 2610 2613 +3
==========================================
+ Hits 6692 6698 +6
+ Misses 3460 3459 -1
Partials 582 582
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable. Can you update the changleog?
Btw, do you happen to have any perf measurements on whether it improves stuff?
I also think some perf numbers would be great. Caches (esp. those that are never invalidated) can cause problems, so I think we should only introduce this extra complexity for a good reason. |
I created some function performer for testing function perfDecorator(fn) {
const results = [];
function printResult() {
console.log('Perf result start:');
console.log('Total calls:', results.length, ' ');
console.log('Min time:', Math.min(...results));
console.log('Max time:', Math.max(...results));
console.log(
'Average time:',
results.reduce((acc, next) => acc + next, 0) / results.length,
);
console.log(
'Sum time:',
results.reduce((acc, next) => acc + next, 0),
);
console.log('Uniq paths:', typeof checkedPaths === 'Object' ? Object.keys(checkedPaths).length) : '';
console.log('Perf result end');
}
return function(path) {
let time = process.hrtime()[1];
const fnResult = fn(path);
time = process.hrtime()[1] - time;
results.push(time);
if (results.length === 4500) {
printResult();
}
return fnResult;
};
}
isFile = perfDecorator(isFile); I tested it in my some project. Before
After
|
Not exactly scientific, but I tested this patch against our test suite with some promising results. Thought you might appreciate a real world report. Each run is just
I could not detect any regressions for single-file test suites with the time reported by jest. |
Woah, that's great! Only thing I'm worried about is if the path starts pointing to a different file or it's a file instead of a directory - do we do any cache invalidation here? |
I'd think that cache invalidation is mostly a problem in watch mode. You could simply bypass the caching completely in watch mode for an easy fix. Apart from watch mode, the only other sources of file changes during runtime I could think of are:
I tested the first scenario by deleting and re-populating all our snapshots (>200) without any problems. The created files match perfectly according to git. With respect to number 3, jest is already running into problems with weird errors, so I don't think this PR matters in that respect. Though it might make future improvements harder. With respect to number 2, you know better if |
It's watch mode I was thinking of, yes. Maybe we could just clear the map when starting a new test run? |
Should the cache perhaps be in |
BTW testing this on a company React app test suite showed about 8% reduction in total time. Pretty good 👍 |
I tried run with const checkedPaths = new Map<string, number>();
console.log('We are here and we have clear Map', checkedPaths.size); And after run test with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this. I'm going to verify myself that the invalidation is working in watch mode. If we can swap out those values to an enum
, we can get this in the release this week!
ddea541
to
4bf5f36
Compare
*/ | ||
function isFile(file: Config.Path): boolean { | ||
let result; | ||
enum IPathType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a big deal, but FYI-- not using the "prefix with I" convention in the Jest codebase.
@scotthovestadt @Connormiha The change is breaking Jest watch mode. Here is a simple test:
|
@ArtemGovorov Patch arrived with |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Summary
For the same path, the function
fs.statSync
can call many times. The more test files, the more often it will be called for the same file or directory.I just added hash table to avoid repeated call for
fs.statSync
.Test plan