gc: don't visit implicit referrers on garbage collection

Before the change garbage collector was not considering
`.drv` and outputs as alive even if configuration says otherwise.
As a result `nix store gc --dry-run` could visit (and parse)
`.drv` files multiple times (worst case it's quadratic).

It happens because `alive` set was populating only runtime closure
without regard for actual configuration. The change fixes it.

Benchmark: my system has about 139MB, 40K `.drv` files.

Performance before the change:

    $ time nix store gc --dry-run
    real    4m22,148s

Performance after the change:

    $ time nix store gc --dry-run
    real    0m14,178s
This commit is contained in:
Sergei Trofimovich 2022-03-17 18:36:45 +00:00
parent a53c1dc96d
commit d58453f72e

View file

@ -678,7 +678,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
alive.insert(start); alive.insert(start);
try { try {
StorePathSet closure; StorePathSet closure;
computeFSClosure(*path, closure); computeFSClosure(*path, closure,
/* flipDirection */ false, gcKeepOutputs, gcKeepDerivations);
for (auto & p : closure) for (auto & p : closure)
alive.insert(p); alive.insert(p);
} catch (InvalidPath &) { } } catch (InvalidPath &) { }