Skip to content
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

Rimraf version 4, first pass #229

Merged
merged 27 commits into from
Jan 12, 2023
Merged

Rimraf version 4, first pass #229

merged 27 commits into from
Jan 12, 2023

Conversation

isaacs
Copy link
Owner

@isaacs isaacs commented May 22, 2021

Remaining todo:

  • bin script
  • take an array of paths and rimraf them all
  • benchmark against system rm -rf subprocess, rimraf v3, and native, but in a way that doesn't just pick a winner at random 😬
  • Drop support for node v10, or handle the lack of fs.promises
  • Provide custom fs functions? Idk, does anyone really need that feature? Dropping it for now. It's easy to bring back if it's an issue, but if no one requests it, better to not have the added complexity.

@isaacs isaacs force-pushed the v4 branch 2 times, most recently from 0970a08 to 71067e7 Compare May 22, 2021 19:29
@coveralls
Copy link

Coverage Status

Coverage increased (+27.0%) to 100.0% when pulling 71067e7 on v4 into 8c10fb8 on main.

1 similar comment
@coveralls
Copy link

Coverage Status

Coverage increased (+27.0%) to 100.0% when pulling 71067e7 on v4 into 8c10fb8 on main.

@coveralls
Copy link

coveralls commented May 22, 2021

Coverage Status

Coverage increased (+27.0%) to 100.0% when pulling 71067e7 on v4 into 8c10fb8 on main.

@isaacs isaacs force-pushed the v4 branch 10 times, most recently from fb34aec to a03ce56 Compare May 25, 2021 22:35
@isaacs
Copy link
Owner Author

isaacs commented May 27, 2021

So.... the move-then-remove approach is about 2x to 10x slower on Windows (for all of the shallow-broad, deep-narrow, and mid-mid folder tree structures I tested, whether the dirs contained a mix of folders and files, all files, or all folders). Also, I can't get the EBUSY/ENOTEMPTY errors to trigger using the posix approach on Windows. (The good news is that the posix approach is comparably performant as the native approach, on macos linux and windows, so that's validating.)

So I think the way forward here is:

  • add EBUSY/ENOTEMPTY/EMFILE/ENFILE exponential backoff
  • when encountering EBUSY on Windows, check if the folder is process.cwd(), and if so, process.chdir(dirname(path)) to get out of it.
  • just have one algorithm used for both posix and windows, and export rimraf.native() and rimraf.manual()
  • use directory-streaming when available (the better to delete very large directories with)

@isaacs
Copy link
Owner Author

isaacs commented May 27, 2021

@damingerdai
Copy link

Is there any progress on this pr?

@albertodiazdorado
Copy link

I'd love to have this thing released. Not having any dependencies sounds very good and it's part of the PR :D

@isaacs
Copy link
Owner Author

isaacs commented Jan 10, 2023

Well, quite a long time coming, eh?

Refactored the windows strategy so that it does a normal naive recursive rm, but first deleting all files, then all folders, and falling back to move-then-remove only when it encounters an error indicating that a file is taking too long to remove from a directory. (Doing move-then-remove in all cases is wayyyyy too slow.)

Also, the windows approach uses exponential backoff (or merely retries in the sync case) to handle EBUSY, ENFILE, and EMFILE errors.

This mirrors the strategy used by the Microsoft brand tools that I could find source code for. In the simple async case, performance is comparable to the posix recursive rm (meaning, better than Node's builtin for the async case, and only slightly worse for the sync case).

Only thing lacking is tests for retry-busy.js, and I should probably add a .d.ts file for it.

isaacs added 9 commits January 9, 2023 16:38
This works around the occasional slowness observed in fs.promises
methods, as well as providing a polyfill for node v10, while also
avoiding the warning about the fs/promises API being experimental on
that version.
Otherwise we get a coverage line missing
Try to avoid the situation where this approach:

    rimraf(path).then(() => rimraf(dirname(path))

fails with EBUSY, due to the semi-presence of marked-for-deletion
entries.
@isaacs isaacs mentioned this pull request Jan 10, 2023
5 tasks
@isaacs isaacs marked this pull request as ready for review January 10, 2023 18:30
@isaacs
Copy link
Owner Author

isaacs commented Jan 11, 2023

It looks like I can't kick off the benchmark workflow until it's merged in, but seems to be showing favorable results locally on windows and macOS, so I'm gonna land it.

@isaacs isaacs merged commit 08bbb06 into main Jan 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants