-
-
Notifications
You must be signed in to change notification settings - Fork 501
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
EMFILE: too many open files when attempting to render a large (170000) number of pages (Eleventy 2.0.0-canary.16) #2627
Comments
@kisaragi-hiu How do you build that site?
UPDATE: Ah, I missed that you were using git submodules. git submodule update --init
brew install cask
make src/_data But now I've graduated to the following error: Loading /tmp/kemdict/process-data.el (source)...
Debugger entered--Lisp error: (file-missing "Cannot open load file" "No such file or directory" "ht")
require(ht)
eval-buffer(#<buffer *load*-56096> nil "/tmp/kemdict/process-data.el" nil t) ; Reading at buffer position 80
load-with-code-conversion("/tmp/kemdict/process-data.el" "/tmp/kemdict/process-data.el" nil nil)
load("process-data")
eval((load "process-data"))
(let ((load-path (cask-load-path (cask-cli--bundle)))) (add-to-list 'load-path cask-cli--path) (eval (read form)))
cask-cli/eval("(load \"process-data\")")
apply(cask-cli/eval "(load \"process-data\")")
commander--handle-command(("eval" "(load \"process-data\")"))
commander-parse(("eval" "(load \"process-data\")"))
(if commander-parsing-done nil (commander-parse (or commander-args (cdr command-line-args-left))))
eval-buffer(#<buffer *load*> nil "/opt/homebrew/Cellar/cask/0.8.8/cask-cli.el" nil t) ; Reading at buffer position 13305
load-with-code-conversion("/opt/homebrew/Cellar/cask/0.8.8/cask-cli.el" "/opt/homebrew/Cellar/cask/0.8.8/cask-cli.el" nil t)
load("/opt/homebrew/Cellar/cask/0.8.8/cask-cli.el" nil t t)
command-line-1(("-scriptload" "/opt/homebrew/Cellar/cask/0.8.8/cask-cli.el" "--" "eval" "(load \"process-data\")"))
command-line()
normal-top-level()
make: *** [src/_data/combined.json] Error 255 |
Comically I got it building on my 2021 MacBook Pro M1 Max w/ 64 GB of RAM… and then it crashed my laptop. Sadly I cloned into my /tmp folder which got reset after rebooting so I'll have to set it up again and see if we can find a solution. ls -lash src/_data
130800 -rw-r--r-- 1 pdehaan staff 64M 26 Oct 17:18 combined.json
147272 -rw-r--r-- 1 pdehaan staff 72M 26 Oct 17:18 dict-moe-revised.json
14704 -rw-r--r-- 1 pdehaan staff 7.2M 26 Oct 17:18 dict-moe-twblg.json |
OK, the site seems to be reliably crashing my computer (but at least isn't giving me EMFILE errors, although not sure that is an improvement over crashing my entire system or just making it unusable). First I tried removing the global data files since they will copy into all of the 170k templates' data cascade (and we're talking about 143 MB worth of JSON data in the src/_data/ filter). ls -lsh src
0 drwxr-xr-x 2 pdehaan staff 64B 26 Oct 17:25 _data
0 drwxr-xr-x 4 pdehaan staff 128B 26 Oct 17:17 _includes
8 -rw-r--r-- 1 pdehaan staff 1.2K 26 Oct 17:17 index.njk
130800 -rw-r--r-- 1 pdehaan staff 64M 26 Oct 17:21 word-pages.11tydata.json
8 -rw-r--r-- 1 pdehaan staff 849B 26 Oct 17:17 word-pages.njk Now my ./src/** directory structure looks roughly like: tree src
src
├── _data/
├── _includes/
│ ├── base.njk
│ └── macros.njk
├── index.njk
├── word-pages.11tydata.json
└── word-pages.njk
2 directories, 5 files And if I build, it seems to:
Per a quick Google search:
Not sure about other OSes, although having 170k+ subdirectories in a single subdirectory is a bit difficult to manage. |
Right, sorry for not formatting the linked site properly. I've created a new branch for testing ( In regards to my site, writing out like 170000 output files is the expected result. At least on Linux it seems to be relatively doable: it builds on my PC (with 8GB of RAM), and it even builds on GitHub Actions (Ubuntu) after I raise the FD limit ( I tested on my PC further, using
I also tried building it on macOS on GitHub Actions. The same error happens:
|
For those of you wanting a temporary fix, I solved this in my own build by patching graceful-fs timeout to be greater than |
PR #3272 is shipping with 3.0.0-alpha.11 |
Describe the bug
EMFILE: too many open files when attempting to render a site with a large number of pages from a large data set.
When it is triggered, it is triggered via EleventyTemplateError.
The number of files being opened is finite: on a system with raised limits it successfully builds.
I have one 40MB json file, containing an array of about 170000 objects, and one template that generates one page per entry. (The site is supposed to be a static dictionary.)
Eleventy version: 2.0.0-canary.16. The site only builds on 2.0 due to #2360.
This behavior has been documented before in #2226 (comment).
Personally, I think this is an issue that can be fixed, as there is no reason why the output files, which depend only on the input file and not on each other, should all be held open at the same time.
To Reproduce
Edit: An earlier version said it took an hour to see the error. That is incorrect: I misread my CI logs, and Eleventy only took 3 minutes.
Edit: This has been rewritten to be more exact and to use error messages from the site generated during the reproduction.
Steps to reproduce the behavior:
Create a new test folder
Generate the test data and put it in
_data/a.json
, containing an array with a large number of objects, with each object having a unique, say, "title" key. I use Emacs for this:The JSON looks something like this:
Create one template to generate pages for each item:
npx @11ty/eleventy --quiet
(--quiet
is to silence the list of rendered files)On a system with higher FD limits, this will succeed.
On a more constrained system, an EMFILE error will be raised (from EleventyTemplateError).
On Linux the FD limit can be lowered for a command like this:
Expected behavior
Writing many files from one template should not cause an EMFILE error.
Environment:
Where the error is encountered:
Where the error is not encountered:
Additional context
I can see that in TemplateWriter.js (generateTemplates) there is essentially an async, unbuffered loop to _generateTemplate → generateMapEntry (Template.js) → _write → writeFile (from graceful-fs).
(This is the source of the EMFILE because it's the only place where EleventyTemplateError can be raised.)
This would rapidly exhaust file descriptors if graceful-fs weren't used. But graceful-fs is used, and it should have handled this, and I don't understand why it's happening.
Perhaps Eleventy should also queue up file writes?
The text was updated successfully, but these errors were encountered: