-
-
Notifications
You must be signed in to change notification settings - Fork 471
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
RFC: #2627: Fix template write EMFILE when writing a large number of pages #2633
Conversation
This does so by limiting the number of concurrent writes. Despite using graceful-fs, for some reason when given a large number of files it would still end up throwing EMFILE. I've set the maximum number of concurrent writes to 1000, just below 1024 which some systems use as the default FD limit. Actually reading the current process FD limit would be better though.
HMM, this looks great! I’m curious: the concurrency check implemented here is template-specific, which means that it will only fix EMFILE issues stemming from a one-to-many pagination template (not from many disparate source templates). Do we want a global concurrency check instead? |
For myself, I would also note the above quoted from the graceful-fs docs: https://www.npmjs.com/package/graceful-fs Just as a sanity check, we are using a promisified writeFile function from graceful-fs: Line 770 in 4e8f1a8
I’m curious if we should be filing this upstream in https://github.com/isaacs/node-graceful-fs/issues?q=is%3Aissue+EMFILE+sort%3Aupdated-desc |
Just thinking out loud here I wonder if the comment I left here is valid or not: isaacs/node-graceful-fs#160 (comment) Maybe using |
I think the other possibility here is that this error might be specific to addPassthroughCopy and that graceful-fs is working fine for template writing? |
Digging into this approach and testing it out, but wanted to say that practically the file limit should likely be set to whatever |
I confirm that this works in both the build and serve contexts it can be run in. This is strange to me and perhaps implies that there is likely a deeper problem in how Eleventy is handling things? I'm not sure. |
Thinking that this might be an issue with the use of I thought this would cover most of the possible |
I did some further experimentation with running this over a longer period of |
Continuing to test and @zachleat I am starting to think the same as you are here, that perhaps Also, worth noting that it appears the OSX max files open is 256. When I checked the setting on my OSX machine, 256 was still the default (12.6.1) |
I solved this in my own build by patching graceful-fs timeout to be greater than |
@epelc I have merged your PR! I think we’ll roll with that approach, as graceful-fs manages simultaneous writes internally (see isaacs/node-graceful-fs#3) |
Putting this one on-hold for now as we investigate the efficacy of #2915 to solve this one (currently on |
FWIW, I still run into this with large builds on Windows using eleventy@ 4501f58. It may still be worth considering this solution as well. |
This fixes #2627. Caveats below, though.
When paginating a data file with a large number of pages, for some reason despite using graceful-fs when given a large number of files it would still end up throwing EMFILE. The error is emitted through TemplateWriter.js (generateTemplates), in an async, unbuffered loop to _generateTemplate → generateMapEntry (Template.js) → _write → writeFile (from graceful-fs).
This PR limits the number of concurrent writes on Eleventy's side to completely avoid hitting the FD limit.
Caveats
I've set the maximum number of concurrent writes to 1000, just below 1024 which some systems use as the default FD limit. Actually reading the current process FD limit would be much better, as this causes an unnecessary slow down for projects that go above 1000 concurrent writes but stays below the actual FD limit. I don't know if there is a standard way of reading the process FD limit that doesn't involve shelling out.
Also, as shown below, for some reason using 1000 as the maximum number of concurrent writes still allows it to build without hitting EMFILE even if the FD limit is lowered to 512. My hypothesis is that this is a low enough number that it doesn't overwhelm graceful-fs.
Results
Without this patch, a 80000-entry project generated with SignpostMarv/11ty-eleventy-issue-2226@2e8f2da fails to build with EMFILE, as documented by #2226 (comment).
With this patch: