nix icon indicating copy to clipboard operation
nix copied to clipboard

`nix develop` extremely slow in large folders

Open happenslol opened this issue 3 years ago • 12 comments

Describe the bug

Using nix develop to open a dev shell inside a repository with lots of files inside takes an inordinate amount of time. This makes tools like nix-direnv pretty much unusable, since opening a new shell takes up to a minute, no matter if anything changed.

In my case, the largest files are build artifacts for rust and node. This is the folder I'm working with:

» du -hs ./* | sort -hr
1.0G    ./src-tauri
59M     ./node_modules
23K     ./yarn.lock
# ... several < 10kb files

Inside src-tauri, there's a target folder containing rust build artifacts, hence the size.
I'm using the following flake.nix:

{
  inputs = {
    nixpkgs.url = "nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};

        libraries = with pkgs;[
          webkitgtk
          gtk3
          cairo
          gdk-pixbuf
          glib.out
          dbus.lib
          openssl_3.out
        ];

        packages = with pkgs; [
          curl
          wget
          pkg-config
          dbus
          openssl_3
          glib
          gtk3
          libsoup
          webkitgtk
        ];
      in
      {
        devShell = pkgs.mkShell {
          buildInputs = packages;

          shellHook =
            let
              joinLibs = libs: builtins.concatStringsSep ":" (builtins.map (x: "${x}/lib") libs);
              libs = joinLibs libraries;
            in
            ''
              export LD_LIBRARY_PATH=${libs}:$LD_LIBRARY_PATH
            '';
        };
      });
}

Running nix develop in this folder takes a minimum of 5 seconds, up to a minute sometimes. Deleting the build artifacts takes the time down to less than a second most of the time.

Steps To Reproduce

  1. Run nix develop inside a folder with large files/folders

Expected behavior

The command should run faster, or it should be possible to tell nix develop to ignore certain files and folders.

nix-env --version output

nix-env (Nix) 2.11.0

Additional context

I'm building a freshly created project of tauri, using their recommended flake setup. Together with nix-direnv and running in tmux, this can effectively lock up the shell when opening new windows, since it's also not possible to cancel the copying... step. Since dependencies and build artifacts will always grow inside project folders, using nix develop is not sustainable for me. Is using the tool in these contexts a non-goal?

happenslol avatar Nov 09 '22 21:11 happenslol

Should be a dupe of #3121 and improve with #6530

SuperSandro2000 avatar Nov 09 '22 22:11 SuperSandro2000

If I'm understanding the issues you linked correctly, there's currently no real workaround except for literally starting the shell inside a subfolder?

happenslol avatar Nov 10 '22 11:11 happenslol

Are you inside a Git repo? Only files tracked by Git should be copied to the store.

Kha avatar Nov 10 '22 11:11 Kha

Yeah, I was specifically talking about the context of using nix develop for repositories in which I'm developing projects. So, executing nix develop outside of the project context is not really an option for me, since I want the flake.nix and flake.lock to be part of the repository.

happenslol avatar Nov 10 '22 12:11 happenslol

Perhaps just to remove the stale tag, this is still a massive issue for me, with nix develop taking 20–30 seconds to start on a large git-tracked folder with large raw-data files (that certainly don't need to ever get involved with Nix)

TheLostLambda avatar Aug 13 '23 06:08 TheLostLambda

My case is quite worse, it's not that big of a project (around 20-40 MB), but it's taking me more than 1m30 to start. I'm not sure in my case, the size or the number of files is causing the bottleneck

Pegasust avatar Sep 29 '23 20:09 Pegasust

I would really like to introduce Nix in our CI at my company, but I feel that this issue is blocking me. We unfortunately have multiple large repos and that seems to not go so well with Nix.

karlssonkennneth avatar Dec 27 '23 09:12 karlssonkennneth

Hey, i am currently facing a similar issue. the repo is ~1gb in size and i would like to use it together direnv. activating the shell takes ~30 seconds. The develop shell is just providing tools to work with the sources, is there any chance to ignore the sources completely?

makefu avatar Apr 21 '24 18:04 makefu

+1. working in a repo with big datasets and and large ml-blobs. taking roughly a minute with top of the line hardware.

is there a proper/right way to use nix in a big repo so that it isn't so slow?

PepperoniPingu avatar May 03 '24 10:05 PepperoniPingu

It takes longer because nix copies all the files in subdirectories if git is not used, or all files tracked by git.

If you do not need nix copying any of your files in your git repo you can put flake.nix into a subdirectory, e.g. ./nix and then refer to it via nix develop path:nix from root of the project.

path makes it to ignore files tracked in git repo and nix only copies everything in ./nix. If you refer to it as nix develop ./nix you essentially doing nix develop git+file:nix which will copy everything tracked in your git repo into nix store.

nickkadutskyi avatar May 03 '24 15:05 nickkadutskyi

@nick-kadutskyi thank you for the suggestion. we are using direnv and use flakes. With use flakes path:<subdir> it seems to be faster, is there any way to check what was actually copied?

makefu avatar May 03 '24 17:05 makefu

@nick-kadutskyi thank you for the suggestion. we are using direnv and use flakes. With use flakes path:<subdir> it seems to be faster, is there any way to check what was actually copied?

Yes, you can check that by running nix flake metadata path:<subdir>, there will be Path field that contains a path to what was copied into nix store.

If you did multiple updates to flake file or imported nix files and ran nix build|develop after each update you got multiple nix store entries for that and I do not know how to find them efficiently. But garbage collection should clean that.

P.S. My .envrc looks like this:

if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then
  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs="
fi

 watch_file nix/flake.nix
 watch_file nix/flake.lock
 watch_file nix/devenv-devShell-custom.nix
 watch_file nix/.env
 watch_file nix/vhost.nix
if ! use flake path:nix --impure
then
  echo "devenv could not be built. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2
fi

nickkadutskyi avatar May 03 '24 17:05 nickkadutskyi

Hello,

I have noticed this issue can come from the repo that don't have git files. I have resolved this issue by initiating an empty repo and just adding/commiting one file. For example:

git init
echo "some random file" >> tmp.txt
git add tmp.txt
git commit -m "simple commit"

ArvinZaker avatar Aug 11 '24 15:08 ArvinZaker