-
Notifications
You must be signed in to change notification settings - Fork 30.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
remove the warning about performance hit in --experimental-detect-module #52803
Comments
It’s certainly much reduced since the initial commit where that warning was added; probably next to nothing for CommonJS files, as that’s what we’ve optimized for. I think it’s probably still a noticeable impact for ESM files that are ambiguous (like a |
yes... 1ms on my machine. |
Well that’s great news, I wasn’t expecting that. 1ms for what, a single file? Or an entire app, like if you had a thousand ESM files in a I guess the question then is what are the downsides of not trying to discourage detection? If I remember correctly, the primary intent with detection was to cover two cases:
With the thinking being that the performance hit of detection was outweighed in these cases by the UX improvement, of having the But if there is no performance hit, or a negligible one, then why wouldn’t everyone just rely on detection all the time? Why bother setting the |
I would not push our luck too much, as 1ms for 1000 modules is 1s, and I've seen apps with that many. I would likely not emit the warning for the top level/entrypoint, but still for everything inside |
The problem there is that warning for We discussed warning on |
Then not warning at all is actually ok. |
I have run a benchmark on one of my "huge" project using ESM on Windows. Here are the results. Node 20 with
Node 22 with
Node 22 with
|
How many ESM files is this, and how many lines of code? I also don’t quite know what to make of these results. The Node 20 numbers are interesting but not really relevant; I’m comparing Node 22 with and without the flag. If I wanted to boil it down to “here’s how much slower the flag makes the app,” am I comparing “Time (mean)” so 739.5 ms to 744.8 ms, or 0.7% slower? Or is it more relevant to compare the “User” numbers, 78.1 to 118.8, so 34% slower? Or is what’s really happening here that the extra CPU cost of detection is irrelevant because the async file I/O takes so much longer? As in, without the flag the CPU is more idle than with the flag, but in the end the process takes almost exactly the same amount of wallclock time because the bottleneck is the I/O and not the CPU? |
The warning is defending against the case where there is a package.json, but it doesn’t contain “type”: “module” even though the .js modules inside are using ESM syntax. To hit the case that it is defending against, you will need to recursively remove all the “type” : “modules” entry in your package.jsons (assuming you have any, and that most of your dependencies use real ESM and count on this to work), and run it with the flag; then compare it with the case where this detection flag is unnecessary (when you still have the type field everywhere). you can’t compare it with a case where you still have package.json with type fields because without the flag that module graph would not load at all currently. |
I am not sure how I can count the loaded file since I am basically starting one of my application and killing it once the http server start (so it is the initialization time of the application). I could re-run it many times to see if the number differ and if the "User" number seems related to the removal of the type in the
Do you mean I should also remove it from all my dependencies to create a fair test? |
@RomainLanz I just mean count the number of JavaScript files and lines of code in your project. So delete/move away The benchmarks that we want to compare are:
Assuming you probably have only one |
I would say yes because removing the warning effectively encourages packages to publish without adding a type field in their package.json and that’s what we don’t want. The warning here would show up in their CI to prevent packages from accidentally publish without the type field. Otherwise it could very well be interpreted as “it’s fine to publish ESM in .js without a type field now!” And the ecosystem start to get slower as it becomes the norm and Node.js commonly has to second guess the module type. |
Usually, the community is pretty good at correcting those things, so I don't expect it to be a problem. |
I don't think the ecosystem is going to start relying on automatic detection. This will break TypeScript, ESLint, etc. |
If we are confident that the ecosystem will add the type field, then those who do won’t be hitting the warning anyway. Either enough people will rely on it so we should prevent it from being a norm, or not enough people will rely on it then only very few people get to be bothered by this warning and it’s harmless to keep. |
Well, my main concern is developers who do |
And not to sound like a heretic on performance, but do we generally warn on performance concerns? Like there are all sorts of slow patterns that we could warn users about— (Aside from experimental warnings that serve the purpose of warning about potential breaking changes; we definitely still want those warnings.) |
That would be highly complicated to count. As said, it is a real world project that depends a lot on third party libraries (coming from the I shared the numbers about to show that there are no real difference with and without the flag. Meaning I believe we can remove the warning.
Will the warning stay when the feature become unflagged? |
If you can run Bash, you can count them via: find . -type f -name "*.js" -not -path "*/node_modules/*" | wc -l And count lines of code via: find . -type f -name "*.js" -not -path "*/node_modules/*" | xargs wc -l I’m excluding
The warning about performance would presumably stay, yes, because it doesn’t relate to the feature’s experimental status. |
Shouldn't the proper solution to that problem be including "type" in |
|
npm is considering adding the type field to npm init: npm/init-package-json#302 (Although it seems the general stance from npm is - people shouldn't really be using I did some local benchmarking out of curiosity - currently loading a ESM graph with detection is about 45% slower than loading the graph without detection (by just adding Running the fixtures from the benchmarks locally, the numbers look like this:
|
@joyeecheung good work. It seems the overhead get worse the more files it adds. Should I close this then? |
In addition to performance hit, I think the warning can also be also updated a bit to remind about the possibility of misinterpretation and be more explicit about what's causing the ESM interpretation. e.g. if a beginner attempts to throw a top-level await into an existing CommonJS file: const fs = require('fs');
await fs.promises.readFile('./README.md'); Previously you get
Now you get
At least, the second hint is confusing/not as practical when they are already modifying a CommonJS codebase (and today it's still very common for CommonJS code bases to have package.json without "type", so it's easier for them to fall into this, whereas ESM code bases that uses |
Note that AWS Lambda decided to disable this feature.
https://aws.amazon.com/blogs/compute/node-js-22-runtime-now-available-in-aws-lambda/ |
I did some experiments with
--experimental-detect-module
and I've found that the added cost of "typeless"package.json
is almost negligible, around 1ms on my system.I recommend we remove the warning.
The text was updated successfully, but these errors were encountered: