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

delete is too slow #172

Open
shahidcodes opened this issue Oct 25, 2023 · 3 comments
Open

delete is too slow #172

shahidcodes opened this issue Oct 25, 2023 · 3 comments
Labels
help wanted Extra attention is needed

Comments

@shahidcodes
Copy link

First of all thanks for this amazing tool.

Describe the bug
npkill finds the node_modules, I hit space to delete, it says deleting and takes like 2-3 min per folder.

To Reproduce
Steps to reproduce the behavior:

  • Run npkill on macos
  • Total size reported was > 20GB
  • Hit space for few folders

Expected behavior
Delete should be fast

Screenshots

image
  • OS: Macos
  • Version: 0.11.3
@cs118651
Copy link

same situation

@zaldih
Copy link
Member

zaldih commented Nov 15, 2023

Related with #121

I am aware that sometimes the deletion is too slow, but I don't quite understand why. Maybe the OS does some security check or something.

Does anyone have any ideas?

@zaldih zaldih added the help wanted Extra attention is needed label Nov 15, 2023
@alan910127
Copy link

@zaldih I also ran into this issue on Linux and looked into the source code. I see that rm -rf is being used to delete the node_modules directory.

According to online benchmarks (see references), the following methods are significantly faster than rm -rf, ranked by speed:

  1. perl
  2. rsync --delete
  3. find -delete

I haven't tested this on MacOS, but since these tools are pretty standard on Linux, they may work similarly on MacOS. A possible approach could be:

import fs from "node:fs";
import path from "node:path";

function executable(exe: string): string | null {
    const envPath = process.env.PATH ?? "";
    const envExt = process.env.PATHEXT ?? "";
    const pathDirs = envPath.replace(/["]+/g, "").split(path.delimiter).filter(Boolean);
    const extensions = envExt.split(";");
    const candidates = pathDirs.flatMap((d) => extensions.map((ext) => path.join(d, exe + ext)));
    try {
        return candidates.filter(checkFileExists)[0] ?? null;
    } catch (e) {
        return null;
    }
}

function checkFileExists(filePath: string): boolean {
    try {
        // assume files under PATH entry directories are executable
        return fs.statSync(filePath).isFile();
    } catch {
        return false;
    }
}

if (executable("perl")) {
    console.log("perl -e 'for(<*>){((stat)[9]<(unlink))}'");
} else if (executable("rsync")) {
    const temp = fs.mkdtempSync("empty");
    console.log(`rsync -a --delete ${temp}/ node_modules/`);
} else if (executable("find")) {
    console.log("find node_modules -type f -delete");
} else {
    console.log("rm -rf node_modules");
}

I'm not entirely sure about the Perl syntax and would need to research it further.

References:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants