`findFirstExistingPath` is extremely slow
See original GitHub issueWe are currently evaluating using tsconfig-paths/register
together with @babel/register
for a pretty large, mostly js project (slowly migrating to ts)
I have found that both of these register hooks have an extreme overhead.
For tsconfig-paths
, most of that seems to come from a huge amount of filesystem accesses. Using it delays the startup of our app from ~5s to ~7s, and a profile shows quite clearly where the time is going:
I haven’t looked too much into what is exactly happening, but what I can say from the profile is that it apparently probes a ton of files before settling on which one to actually use. I will continue investigating and will update this issue with any findings.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:4
- Comments:19 (10 by maintainers)
Top Results From Across the Web
FindFirst is very slow - Lazarus Forum
I am using FindFisrt/FindNext in my app to search and find files on a specific folders. I just noticed this function is extremely...
Read more >Is there a workaround for Java's poor performance on walking ...
If the processing is very fast right now it may be slowed down a bit. This is because the information prefetched is no...
Read more >Slow Step Required - Help - UiPath Community Forum
I'm totally new to this and i'm creating my first flow by using web record. the process i am trying to do is...
Read more >What is the fastest way to check if a file exists? - Windows API
FindFirst is definitively the slowest. It needs at least two calls (+ FindClose), and maintain some state in-between. GetFileAtributes() is the ...
Read more >Any possibility to make backend uia faster · Issue #256 - GitHub
hi, any progress with the issue? any possibility to make uia work faster? it is very slow if I have multiply winforms in...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Hi all, just run into the same problem that the
findFirstExistingPath
is extremely slow, but by looking at the frame graph, I think there’s also another problem that causes it extremely slow:TL;DR
Using
fs.statSync
insidefindFirstExistingPath
when resolving path make it super slow for programs that usesrequire()
inline. Suggest to fix with caching.The problem
Using Typescript and postcards with webpack to build our own web application. Most of the part that includes
require
is super slow, like this part inhtml-webpack-plugin
:Reason
Every time the
require
is called, theModule._resolveFilename
is called (which we replaced with our own version) and it uses anfs.statSync
!!For some Js project, there’re still quite a lot of places that put the require in the function body instead of extracting then out to the top of the script, which cause this problem. But still, it is not a good thing that the part called
xxxSync
is not cached as it would easily become slow.Screenshots: The parts repeat and take quite a lot of times
It is stocked by the
fs.statSync
Suggestion
I’m not familiar with the ts-config code base but I think we can introduce cache to the part https://github.com/dividab/tsconfig-paths/blob/master/src/register.ts#L82 maybe something like this:
So monorepos is not typescript specific. It just means you have several packages in the same git repo. So you split your app in several npm packages with their own package.json even if you don’t intend to publish them because then you can import them using
import * as Utils from "@myapp/utils"
. For this to work you need to create symlinks in the top-levelnode_modules
that link to the code in each package. There are several tools that help with this, I would suggest reading up on yarn workspaces or if you are not using yarn then you can use lerna. Here is an exampe of using typescript with a monorepo (although in this example paths are still used but still it is a good example to start with). You can google “typescript monorepo” for more examples.Once you have split your app into separate packages, you can make
tsc
build only the packages that have changed and thus get faster build times (this feature is known as “project references” or tsc --build). Here is one example repo for this approach. There is also this issue which may contain some useful links.The basic idea is that all packages reference each other through regular node resolution, which is just look upward for
node_modules/packagename
. And since the symlinks are in place the packages will find each other without having to resort to relative file paths in imports.