-
-
Notifications
You must be signed in to change notification settings - Fork 433
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
Added cache for some FS operations while compile #829
Changes from all commits
af7ab34
370cf78
9c4edbf
c7c5409
7a239b7
1254e0f
6a7638a
4671658
16f6f39
3588bb0
3cf2796
453bb6a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,15 +14,23 @@ import { | |
Webpack | ||
} from './interfaces'; | ||
|
||
export type Action = () => void; | ||
|
||
export interface ServiceHostWhichMayBeCacheable { | ||
servicesHost: typescript.LanguageServiceHost; | ||
clearCache: Action | null; | ||
} | ||
|
||
/** | ||
* Create the TypeScript language service | ||
*/ | ||
export function makeServicesHost( | ||
scriptRegex: RegExp, | ||
log: logger.Logger, | ||
loader: Webpack, | ||
instance: TSInstance | ||
) { | ||
instance: TSInstance, | ||
enableFileCaching: boolean | ||
): ServiceHostWhichMayBeCacheable { | ||
const { | ||
compiler, | ||
compilerOptions, | ||
|
@@ -52,9 +60,12 @@ export function makeServicesHost( | |
const moduleResolutionHost: ModuleResolutionHost = { | ||
fileExists, | ||
readFile: readFileWithFallback, | ||
realpath: compiler.sys.realpath | ||
realpath: compiler.sys.realpath, | ||
directoryExists: compiler.sys.directoryExists | ||
}; | ||
|
||
const clearCache = enableFileCaching ? addCache(moduleResolutionHost) : null; | ||
|
||
// loader.context seems to work fine on Linux / Mac regardless causes problems for @types resolution on Windows for TypeScript < 2.3 | ||
const getCurrentDirectory = () => loader.context; | ||
|
||
|
@@ -97,13 +108,15 @@ export function makeServicesHost( | |
/** | ||
* For @types expansion, these two functions are needed. | ||
*/ | ||
directoryExists: compiler.sys.directoryExists, | ||
directoryExists: moduleResolutionHost.directoryExists, | ||
|
||
useCaseSensitiveFileNames: () => compiler.sys.useCaseSensitiveFileNames, | ||
|
||
realpath: moduleResolutionHost.realpath, | ||
|
||
// The following three methods are necessary for @types resolution from TS 2.4.1 onwards see: https://github.com/Microsoft/TypeScript/issues/16772 | ||
fileExists: compiler.sys.fileExists, | ||
readFile: compiler.sys.readFile, | ||
fileExists: moduleResolutionHost.fileExists, | ||
readFile: moduleResolutionHost.readFile, | ||
readDirectory: compiler.sys.readDirectory, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. was there a reason that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope. I didn't see this function in the profiler before and I don't think that it can reduce perf, but if you want - I can check and provide the stats. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you could check that'd be awesome. I'm currently working on tweaking the test packs so they can be made to work against a variety of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Unfortunately for now I'm away from work and cannot check it. I'll do it in next couple of days and will provide here results. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @johnnyreilly I just checked |
||
|
||
getCurrentDirectory, | ||
|
@@ -137,7 +150,7 @@ export function makeServicesHost( | |
getCustomTransformers: () => instance.transformers | ||
}; | ||
|
||
return servicesHost; | ||
return { servicesHost, clearCache }; | ||
} | ||
|
||
/** | ||
|
@@ -509,3 +522,49 @@ function populateDependencyGraphs( | |
] = true; | ||
}); | ||
} | ||
|
||
type CacheableFunction = Extract< | ||
keyof typescript.ModuleResolutionHost, | ||
'fileExists' | 'directoryExists' | 'realpath' | ||
>; | ||
const cacheableFunctions: CacheableFunction[] = [ | ||
'fileExists', | ||
'directoryExists', | ||
'realpath' | ||
]; | ||
|
||
function addCache(servicesHost: typescript.ModuleResolutionHost) { | ||
const clearCacheFunctions: Action[] = []; | ||
|
||
cacheableFunctions.forEach((functionToCache: CacheableFunction) => { | ||
const originalFunction = servicesHost[functionToCache]; | ||
if (originalFunction !== undefined) { | ||
const cache = createCache<ReturnType<typeof originalFunction>>(originalFunction); | ||
servicesHost[ | ||
functionToCache | ||
] = cache.getCached as typescript.ModuleResolutionHost[CacheableFunction]; | ||
clearCacheFunctions.push(cache.clear); | ||
} | ||
}); | ||
|
||
return () => clearCacheFunctions.forEach(clear => clear()); | ||
} | ||
|
||
function createCache<TOut>(originalFunction: (arg: string) => TOut) { | ||
const cache = new Map<string, TOut>(); | ||
return { | ||
clear: () => { | ||
cache.clear(); | ||
}, | ||
getCached: (arg: string) => { | ||
let res = cache.get(arg); | ||
if (res !== undefined) { | ||
return res; | ||
} | ||
|
||
res = originalFunction(arg); | ||
cache.set(arg, res); | ||
return res; | ||
} | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"overrides": [ | ||
{ | ||
"files": "*.js", | ||
"options": { | ||
"singleQuote": true | ||
} | ||
} | ||
] | ||
} |
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.
We didn't have
realpath
before I think; I'm just curious; what is it used for?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.
To resolve path to original one. For example, if you have symlink.
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.
Ah - we've had since we added symlink support here: https://github.com/TypeStrong/ts-loader/pull/774/files
We just didn't supply it to the
LanguageServiceHost
until now though. I'm kind of surprised we didn't get a compilation error previously 🤔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.
Hm, interesting. Perhaps microsoft/TypeScript#12020 (comment) (and the whole PR) is related to this.