diff --git a/src/libexpr-c/nix_api_expr.cc b/src/libexpr-c/nix_api_expr.cc index a028202ae..46e08b5f7 100644 --- a/src/libexpr-c/nix_api_expr.cc +++ b/src/libexpr-c/nix_api_expr.cc @@ -16,7 +16,7 @@ #include "nix_api_util_internal.h" #if NIX_USE_BOEHMGC -# include +# include #endif /** @@ -207,28 +207,20 @@ void nix_state_free(EvalState * state) } #if NIX_USE_BOEHMGC -std::unordered_map< +boost::concurrent_flat_map< const void *, unsigned int, std::hash, std::equal_to, traceable_allocator>> - nix_refcounts; - -std::mutex nix_refcount_lock; + nix_refcounts{}; nix_err nix_gc_incref(nix_c_context * context, const void * p) { if (context) context->last_err_code = NIX_OK; try { - std::scoped_lock lock(nix_refcount_lock); - auto f = nix_refcounts.find(p); - if (f != nix_refcounts.end()) { - f->second++; - } else { - nix_refcounts[p] = 1; - } + nix_refcounts.insert_or_visit({p, 1}, [](auto & kv) { kv.second++; }); } NIXC_CATCH_ERRS } @@ -239,12 +231,12 @@ nix_err nix_gc_decref(nix_c_context * context, const void * p) if (context) context->last_err_code = NIX_OK; try { - std::scoped_lock lock(nix_refcount_lock); - auto f = nix_refcounts.find(p); - if (f != nix_refcounts.end()) { - if (--f->second == 0) - nix_refcounts.erase(f); - } else + bool fail = true; + nix_refcounts.erase_if(p, [&](auto & kv) { + fail = false; + return !--kv.second; + }); + if (fail) throw std::runtime_error("nix_gc_decref: object was not referenced"); } NIXC_CATCH_ERRS diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index c107c6bc2..f2520bcda 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -4571,11 +4571,13 @@ struct RegexCache std::regex regex; /* No std::regex constructor overload from std::string_view, but can be constructed from a pointer + size or an iterator range. */ - cache.try_emplace_and_cvisit(re, - /*s=*/re.data(), /*count=*/re.size(), std::regex::extended, + cache.try_emplace_and_cvisit( + re, + /*s=*/re.data(), + /*count=*/re.size(), + std::regex::extended, [®ex](const auto & kv) { regex = kv.second; }, - [®ex](const auto & kv) { regex = kv.second; } - ); + [®ex](const auto & kv) { regex = kv.second; }); return regex; } }; diff --git a/src/libexpr/print.cc b/src/libexpr/print.cc index 5338e365e..071addc1a 100644 --- a/src/libexpr/print.cc +++ b/src/libexpr/print.cc @@ -1,5 +1,4 @@ #include -#include #include #include "nix/expr/print.hh" @@ -10,6 +9,8 @@ #include "nix/util/english.hh" #include "nix/expr/eval.hh" +#include + namespace nix { void printElided( @@ -81,7 +82,7 @@ std::ostream & printLiteralBool(std::ostream & str, bool boolean) // For example `or' doesn't need to be quoted. bool isReservedKeyword(const std::string_view str) { - static const std::unordered_set reservedKeywords = { + static const boost::unordered_flat_set reservedKeywords = { "if", "then", "else", "assert", "with", "let", "in", "rec", "inherit"}; return reservedKeywords.contains(str); } diff --git a/src/libfetchers/filtering-source-accessor.cc b/src/libfetchers/filtering-source-accessor.cc index 17f224ad2..d0991ae23 100644 --- a/src/libfetchers/filtering-source-accessor.cc +++ b/src/libfetchers/filtering-source-accessor.cc @@ -1,5 +1,7 @@ #include "nix/fetchers/filtering-source-accessor.hh" +#include + namespace nix { std::optional FilteringSourceAccessor::getPhysicalPath(const CanonPath & path) @@ -57,12 +59,12 @@ void FilteringSourceAccessor::checkAccess(const CanonPath & path) struct AllowListSourceAccessorImpl : AllowListSourceAccessor { std::set allowedPrefixes; - std::unordered_set allowedPaths; + boost::unordered_flat_set> allowedPaths; AllowListSourceAccessorImpl( ref next, std::set && allowedPrefixes, - std::unordered_set && allowedPaths, + boost::unordered_flat_set> && allowedPaths, MakeNotAllowedError && makeNotAllowedError) : AllowListSourceAccessor(SourcePath(next), std::move(makeNotAllowedError)) , allowedPrefixes(std::move(allowedPrefixes)) @@ -84,7 +86,7 @@ struct AllowListSourceAccessorImpl : AllowListSourceAccessor ref AllowListSourceAccessor::create( ref next, std::set && allowedPrefixes, - std::unordered_set && allowedPaths, + boost::unordered_flat_set> && allowedPaths, MakeNotAllowedError && makeNotAllowedError) { return make_ref( diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 1861838ed..4ed94a4ed 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -30,8 +30,9 @@ #include #include +#include +#include #include -#include #include #include #include @@ -315,7 +316,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this uint64_t getRevCount(const Hash & rev) override { - std::unordered_set done; + boost::unordered_flat_set> done; std::queue todo; todo.push(peelObject(lookupObject(*this, hashToOID(rev)).get(), GIT_OBJECT_COMMIT)); @@ -569,7 +570,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this void verifyCommit(const Hash & rev, const std::vector & publicKeys) override { // Map of SSH key types to their internal OpenSSH representations - static const std::unordered_map keyTypeMap = { + static const boost::unordered_flat_map keyTypeMap = { {"ssh-dsa", "ssh-dsa"}, {"ssh-ecdsa", "ssh-ecdsa"}, {"ssh-ecdsa-sk", "sk-ecdsa-sha2-nistp256@openssh.com"}, @@ -816,7 +817,7 @@ struct GitSourceAccessor : SourceAccessor return toHash(*git_tree_entry_id(entry)); } - std::unordered_map lookupCache; + boost::unordered_flat_map> lookupCache; /* Recursively look up 'path' relative to the root. */ git_tree_entry * lookup(State & state, const CanonPath & path) @@ -1253,7 +1254,7 @@ GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllow makeFSSourceAccessor(path), std::set{wd.files}, // Always allow access to the root, but not its children. - std::unordered_set{CanonPath::root}, + boost::unordered_flat_set>{CanonPath::root}, std::move(makeNotAllowedError)) .cast(); if (exportIgnore) diff --git a/src/libfetchers/include/nix/fetchers/filtering-source-accessor.hh b/src/libfetchers/include/nix/fetchers/filtering-source-accessor.hh index 70e837ff4..1d4028be5 100644 --- a/src/libfetchers/include/nix/fetchers/filtering-source-accessor.hh +++ b/src/libfetchers/include/nix/fetchers/filtering-source-accessor.hh @@ -2,7 +2,7 @@ #include "nix/util/source-path.hh" -#include +#include namespace nix { @@ -72,7 +72,7 @@ struct AllowListSourceAccessor : public FilteringSourceAccessor static ref create( ref next, std::set && allowedPrefixes, - std::unordered_set && allowedPaths, + boost::unordered_flat_set> && allowedPaths, MakeNotAllowedError && makeNotAllowedError); using FilteringSourceAccessor::FilteringSourceAccessor; diff --git a/src/libflake/lockfile.cc b/src/libflake/lockfile.cc index 94e7f11f1..f381a57e6 100644 --- a/src/libflake/lockfile.cc +++ b/src/libflake/lockfile.cc @@ -1,5 +1,3 @@ -#include - #include "nix/fetchers/fetch-settings.hh" #include "nix/flake/settings.hh" #include "nix/flake/lockfile.hh" @@ -9,6 +7,7 @@ #include #include +#include #include #include @@ -162,7 +161,7 @@ std::pair LockFile::toJSON() const { nlohmann::json nodes; KeyMap nodeKeys; - std::unordered_set keys; + boost::unordered_flat_set keys; std::function node)> dumpNode; diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index a1831efc6..84889ceac 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -11,6 +11,7 @@ #include "nix/util/json-utils.hh" #include +#include #include namespace nix { @@ -834,7 +835,7 @@ DerivationType BasicDerivation::type() const throw Error("can't mix derivation output types"); } -Sync drvHashes; +DrvHashes drvHashes; /* pathDerivationModulo and hashDerivationModulo are mutually recursive */ @@ -844,16 +845,13 @@ Sync drvHashes; */ static const DrvHash pathDerivationModulo(Store & store, const StorePath & drvPath) { - { - auto hashes = drvHashes.lock(); - auto h = hashes->find(drvPath); - if (h != hashes->end()) { - return h->second; - } + std::optional hash; + if (drvHashes.cvisit(drvPath, [&hash](const auto & kv) { hash.emplace(kv.second); })) { + return *hash; } auto h = hashDerivationModulo(store, store.readInvalidDerivation(drvPath), false); // Cache it - drvHashes.lock()->insert_or_assign(drvPath, h); + drvHashes.insert_or_assign(drvPath, h); return h; } diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 385215fe0..dd33f5f84 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -1,6 +1,7 @@ #include "nix/store/derivations.hh" #include "nix/store/globals.hh" #include "nix/store/local-store.hh" +#include "nix/store/path.hh" #include "nix/util/finally.hh" #include "nix/util/unix-domain-socket.hh" #include "nix/util/signals.hh" @@ -13,14 +14,10 @@ # include "nix/util/processes.hh" #endif +#include +#include #include - -#include #include -#include -#include - -#include #include #include #include @@ -314,7 +311,7 @@ Roots LocalStore::findRoots(bool censor) /** * Key is a mere string because cannot has path with macOS's libc++ */ -typedef std::unordered_map> UncheckedRoots; +typedef boost::unordered_flat_map> UncheckedRoots; static void readProcLink(const std::filesystem::path & file, UncheckedRoots & roots) { @@ -463,13 +460,13 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) bool gcKeepOutputs = settings.gcKeepOutputs; bool gcKeepDerivations = settings.gcKeepDerivations; - std::unordered_set roots, dead, alive; + boost::unordered_flat_set> roots, dead, alive; struct Shared { // The temp roots only store the hash part to make it easier to // ignore suffixes like '.lock', '.chroot' and '.check'. - std::unordered_set tempRoots; + boost::unordered_flat_set tempRoots; // Hash part of the store path currently being deleted, if // any. @@ -672,7 +669,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } }; - std::unordered_map referrersCache; + boost::unordered_flat_map> referrersCache; /* Helper function that visits all paths reachable from `start` via the referrers edges and optionally derivers and derivation diff --git a/src/libstore/include/nix/store/derivations.hh b/src/libstore/include/nix/store/derivations.hh index 18479b425..08bb7183f 100644 --- a/src/libstore/include/nix/store/derivations.hh +++ b/src/libstore/include/nix/store/derivations.hh @@ -11,7 +11,7 @@ #include "nix/util/sync.hh" #include "nix/util/variant-wrapper.hh" -#include +#include #include namespace nix { @@ -507,13 +507,23 @@ DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOut */ std::map staticOutputHashes(Store & store, const Derivation & drv); +struct DrvHashFct +{ + using is_avalanching = std::true_type; + + std::size_t operator()(const StorePath & path) const noexcept + { + return std::hash{}(path.to_string()); + } +}; + /** * Memoisation of hashDerivationModulo(). */ -typedef std::map DrvHashes; +typedef boost::concurrent_flat_map DrvHashes; // FIXME: global, though at least thread-safe. -extern Sync drvHashes; +extern DrvHashes drvHashes; struct Source; struct Sink; diff --git a/src/libstore/include/nix/store/gc-store.hh b/src/libstore/include/nix/store/gc-store.hh index 9f2255025..fba9d6079 100644 --- a/src/libstore/include/nix/store/gc-store.hh +++ b/src/libstore/include/nix/store/gc-store.hh @@ -1,13 +1,13 @@ #pragma once ///@file -#include - #include "nix/store/store-api.hh" +#include +#include namespace nix { -typedef std::unordered_map> Roots; +typedef boost::unordered_flat_map, std::hash> Roots; struct GCOptions { diff --git a/src/libstore/include/nix/store/local-store.hh b/src/libstore/include/nix/store/local-store.hh index 1184be8ed..b871aaee2 100644 --- a/src/libstore/include/nix/store/local-store.hh +++ b/src/libstore/include/nix/store/local-store.hh @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace nix { @@ -442,7 +442,7 @@ private: std::pair createTempDirInStore(); - typedef std::unordered_set InodeHash; + typedef boost::unordered_flat_set InodeHash; InodeHash loadInodeHash(); Strings readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash); diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 8de41fe19..c5e1747c1 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -1,5 +1,3 @@ -#include - #include "nix/store/derivations.hh" #include "nix/store/parsed-derivations.hh" #include "nix/store/derivation-options.hh" @@ -13,6 +11,8 @@ #include "nix/store/filetransfer.hh" #include "nix/util/strings.hh" +#include + namespace nix { void Store::computeFSClosure( @@ -106,7 +106,7 @@ MissingPaths Store::queryMissing(const std::vector & targets) struct State { - std::unordered_set done; + boost::unordered_flat_set done; MissingPaths res; }; diff --git a/src/libutil/include/nix/util/canon-path.hh b/src/libutil/include/nix/util/canon-path.hh index cb8b4325d..334c9e332 100644 --- a/src/libutil/include/nix/util/canon-path.hh +++ b/src/libutil/include/nix/util/canon-path.hh @@ -258,7 +258,7 @@ public: */ std::string makeRelative(const CanonPath & path) const; - friend class std::hash; + friend struct std::hash; }; std::ostream & operator<<(std::ostream & stream, const CanonPath & path); @@ -268,6 +268,8 @@ std::ostream & operator<<(std::ostream & stream, const CanonPath & path); template<> struct std::hash { + using is_avalanching = std::true_type; + std::size_t operator()(const nix::CanonPath & s) const noexcept { return std::hash{}(s.path); diff --git a/src/libutil/linux/cgroup.cc b/src/libutil/linux/cgroup.cc index 20d19ae7d..9e78ac6d2 100644 --- a/src/libutil/linux/cgroup.cc +++ b/src/libutil/linux/cgroup.cc @@ -4,10 +4,10 @@ #include "nix/util/file-system.hh" #include "nix/util/finally.hh" +#include #include #include #include -#include #include #include @@ -76,7 +76,7 @@ static CgroupStats destroyCgroup(const std::filesystem::path & cgroup, bool retu int round = 1; - std::unordered_set pidsShown; + boost::unordered_flat_set pidsShown; while (true) { auto pids = tokenizeString>(readFile(procsFile)); diff --git a/src/libutil/posix-source-accessor.cc b/src/libutil/posix-source-accessor.cc index b932f6ab5..877c63331 100644 --- a/src/libutil/posix-source-accessor.cc +++ b/src/libutil/posix-source-accessor.cc @@ -104,7 +104,7 @@ std::optional PosixSourceAccessor::cachedLstat(const CanonPath & pa if (cache.size() >= 16384) cache.clear(); - cache.emplace(absPath, st); + cache.emplace(std::move(absPath), st); return st; } diff --git a/src/nix/env.cc b/src/nix/env.cc index d91ee72d7..c8fb5bee0 100644 --- a/src/nix/env.cc +++ b/src/nix/env.cc @@ -71,7 +71,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment auto outPaths = Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables); - std::unordered_set done; + boost::unordered_flat_set> done; std::queue todo; for (auto & path : outPaths) todo.push(path);