1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 03:56:01 +01:00

Merge pull request #13926 from NaN-git/opt_boost-unordered

replace all occurences of std::unordered_* by equivalents from boost
This commit is contained in:
Jörg Thalheim 2025-09-12 11:46:42 +02:00 committed by GitHub
commit 377b60ee9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 130 additions and 119 deletions

View file

@ -16,7 +16,7 @@
#include "nix_api_util_internal.h" #include "nix_api_util_internal.h"
#if NIX_USE_BOEHMGC #if NIX_USE_BOEHMGC
# include <mutex> # include <boost/unordered/concurrent_flat_map.hpp>
#endif #endif
/** /**
@ -207,28 +207,20 @@ void nix_state_free(EvalState * state)
} }
#if NIX_USE_BOEHMGC #if NIX_USE_BOEHMGC
std::unordered_map< boost::concurrent_flat_map<
const void *, const void *,
unsigned int, unsigned int,
std::hash<const void *>, std::hash<const void *>,
std::equal_to<const void *>, std::equal_to<const void *>,
traceable_allocator<std::pair<const void * const, unsigned int>>> traceable_allocator<std::pair<const void * const, unsigned int>>>
nix_refcounts; nix_refcounts{};
std::mutex nix_refcount_lock;
nix_err nix_gc_incref(nix_c_context * context, const void * p) nix_err nix_gc_incref(nix_c_context * context, const void * p)
{ {
if (context) if (context)
context->last_err_code = NIX_OK; context->last_err_code = NIX_OK;
try { try {
std::scoped_lock lock(nix_refcount_lock); nix_refcounts.insert_or_visit({p, 1}, [](auto & kv) { kv.second++; });
auto f = nix_refcounts.find(p);
if (f != nix_refcounts.end()) {
f->second++;
} else {
nix_refcounts[p] = 1;
}
} }
NIXC_CATCH_ERRS NIXC_CATCH_ERRS
} }
@ -239,12 +231,12 @@ nix_err nix_gc_decref(nix_c_context * context, const void * p)
if (context) if (context)
context->last_err_code = NIX_OK; context->last_err_code = NIX_OK;
try { try {
std::scoped_lock lock(nix_refcount_lock); bool fail = true;
auto f = nix_refcounts.find(p); nix_refcounts.erase_if(p, [&](auto & kv) {
if (f != nix_refcounts.end()) { fail = false;
if (--f->second == 0) return !--kv.second;
nix_refcounts.erase(f); });
} else if (fail)
throw std::runtime_error("nix_gc_decref: object was not referenced"); throw std::runtime_error("nix_gc_decref: object was not referenced");
} }
NIXC_CATCH_ERRS NIXC_CATCH_ERRS

View file

@ -1085,7 +1085,9 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial)
void EvalState::resetFileCache() void EvalState::resetFileCache()
{ {
fileEvalCache.clear(); fileEvalCache.clear();
fileEvalCache.rehash(0);
fileParseCache.clear(); fileParseCache.clear();
fileParseCache.rehash(0);
inputCache->clear(); inputCache->clear();
} }
@ -2370,10 +2372,9 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat
if (nix::isDerivation(path.path.abs())) if (nix::isDerivation(path.path.abs()))
error<EvalError>("file names are not allowed to end in '%1%'", drvExtension).debugThrow(); error<EvalError>("file names are not allowed to end in '%1%'", drvExtension).debugThrow();
auto dstPathCached = get(*srcToStore.lock(), path); std::optional<StorePath> dstPath;
if (!srcToStore.cvisit(path, [&dstPath](const auto & kv) { dstPath.emplace(kv.second); })) {
auto dstPath = dstPathCached ? *dstPathCached : [&]() { dstPath.emplace(fetchToStore(
auto dstPath = fetchToStore(
fetchSettings, fetchSettings,
*store, *store,
path.resolveSymlinks(SymlinkResolution::Ancestors), path.resolveSymlinks(SymlinkResolution::Ancestors),
@ -2381,15 +2382,14 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat
path.baseName(), path.baseName(),
ContentAddressMethod::Raw::NixArchive, ContentAddressMethod::Raw::NixArchive,
nullptr, nullptr,
repair); repair));
allowPath(dstPath); allowPath(*dstPath);
srcToStore.lock()->try_emplace(path, dstPath); srcToStore.try_emplace(path, *dstPath);
printMsg(lvlChatty, "copied source '%1%' -> '%2%'", path, store->printStorePath(dstPath)); printMsg(lvlChatty, "copied source '%1%' -> '%2%'", path, store->printStorePath(*dstPath));
return dstPath; }
}();
context.insert(NixStringContextElem::Opaque{.path = dstPath}); context.insert(NixStringContextElem::Opaque{.path = *dstPath});
return dstPath; return *dstPath;
} }
SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx) SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx)

View file

@ -20,6 +20,8 @@
// For `NIX_USE_BOEHMGC`, and if that's set, `GC_THREADS` // For `NIX_USE_BOEHMGC`, and if that's set, `GC_THREADS`
#include "nix/expr/config.hh" #include "nix/expr/config.hh"
#include <boost/unordered/concurrent_flat_map.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <map> #include <map>
#include <optional> #include <optional>
#include <functional> #include <functional>
@ -162,7 +164,7 @@ typedef std::
map<std::string, Value *, std::less<std::string>, traceable_allocator<std::pair<const std::string, Value *>>> map<std::string, Value *, std::less<std::string>, traceable_allocator<std::pair<const std::string, Value *>>>
ValMap; ValMap;
typedef std::unordered_map<PosIdx, DocComment> DocCommentMap; typedef boost::unordered_flat_map<PosIdx, DocComment, std::hash<PosIdx>> DocCommentMap;
struct Env struct Env
{ {
@ -367,7 +369,7 @@ public:
bool inDebugger = false; bool inDebugger = false;
int trylevel; int trylevel;
std::list<DebugTrace> debugTraces; std::list<DebugTrace> debugTraces;
std::map<const Expr *, const std::shared_ptr<const StaticEnv>> exprEnvs; boost::unordered_flat_map<const Expr *, const std::shared_ptr<const StaticEnv>> exprEnvs;
const std::shared_ptr<const StaticEnv> getStaticEnv(const Expr & expr) const const std::shared_ptr<const StaticEnv> getStaticEnv(const Expr & expr) const
{ {
@ -410,12 +412,12 @@ private:
/* Cache for calls to addToStore(); maps source paths to the store /* Cache for calls to addToStore(); maps source paths to the store
paths. */ paths. */
Sync<std::unordered_map<SourcePath, StorePath>> srcToStore; boost::concurrent_flat_map<SourcePath, StorePath, std::hash<SourcePath>> srcToStore;
/** /**
* A cache from path names to parse trees. * A cache from path names to parse trees.
*/ */
typedef std::unordered_map< typedef boost::unordered_flat_map<
SourcePath, SourcePath,
Expr *, Expr *,
std::hash<SourcePath>, std::hash<SourcePath>,
@ -427,7 +429,7 @@ private:
/** /**
* A cache from path names to values. * A cache from path names to values.
*/ */
typedef std::unordered_map< typedef boost::unordered_flat_map<
SourcePath, SourcePath,
Value, Value,
std::hash<SourcePath>, std::hash<SourcePath>,
@ -440,11 +442,12 @@ private:
* Associate source positions of certain AST nodes with their preceding doc comment, if they have one. * Associate source positions of certain AST nodes with their preceding doc comment, if they have one.
* Grouped by file. * Grouped by file.
*/ */
std::unordered_map<SourcePath, DocCommentMap> positionToDocComment; boost::unordered_flat_map<SourcePath, DocCommentMap, std::hash<SourcePath>> positionToDocComment;
LookupPath lookupPath; LookupPath lookupPath;
std::map<std::string, std::optional<SourcePath>> lookupPathResolved; boost::unordered_flat_map<std::string, std::optional<SourcePath>, StringViewHash, std::equal_to<>>
lookupPathResolved;
/** /**
* Cache used by prim_match(). * Cache used by prim_match().
@ -718,11 +721,11 @@ public:
/** /**
* Internal primops not exposed to the user. * Internal primops not exposed to the user.
*/ */
std::unordered_map< boost::unordered_flat_map<
std::string, std::string,
Value *, Value *,
std::hash<std::string>, StringViewHash,
std::equal_to<std::string>, std::equal_to<>,
traceable_allocator<std::pair<const std::string, Value *>>> traceable_allocator<std::pair<const std::string, Value *>>>
internalPrimOps; internalPrimOps;
@ -989,10 +992,10 @@ private:
bool countCalls; bool countCalls;
typedef std::map<std::string, size_t> PrimOpCalls; typedef boost::unordered_flat_map<std::string, size_t, StringViewHash, std::equal_to<>> PrimOpCalls;
PrimOpCalls primOpCalls; PrimOpCalls primOpCalls;
typedef std::map<ExprLambda *, size_t> FunctionCalls; typedef boost::unordered_flat_map<ExprLambda *, size_t> FunctionCalls;
FunctionCalls functionCalls; FunctionCalls functionCalls;
/** Evaluation/call profiler. */ /** Evaluation/call profiler. */
@ -1000,7 +1003,7 @@ private:
void incrFunctionCall(ExprLambda * fun); void incrFunctionCall(ExprLambda * fun);
typedef std::map<PosIdx, size_t> AttrSelects; typedef boost::unordered_flat_map<PosIdx, size_t, std::hash<PosIdx>> AttrSelects;
AttrSelects attrSelects; AttrSelects attrSelects;
friend struct ExprOpUpdate; friend struct ExprOpUpdate;

View file

@ -71,7 +71,7 @@ struct LexerState
/** /**
* @brief Maps some positions to a DocComment, where the comment is relevant to the location. * @brief Maps some positions to a DocComment, where the comment is relevant to the location.
*/ */
std::unordered_map<PosIdx, DocComment> & positionToDocComment; DocCommentMap & positionToDocComment;
PosTable & positions; PosTable & positions;
PosTable::Origin origin; PosTable::Origin origin;

View file

@ -12,6 +12,7 @@
#include "nix/expr/print-options.hh" #include "nix/expr/print-options.hh"
#include "nix/util/checked-arithmetic.hh" #include "nix/util/checked-arithmetic.hh"
#include <boost/unordered/unordered_flat_map_fwd.hpp>
#include <nlohmann/json_fwd.hpp> #include <nlohmann/json_fwd.hpp>
namespace nix { namespace nix {
@ -1195,7 +1196,7 @@ void Value::mkBlackhole()
} }
typedef std::vector<Value *, traceable_allocator<Value *>> ValueVector; typedef std::vector<Value *, traceable_allocator<Value *>> ValueVector;
typedef std::unordered_map< typedef boost::unordered_flat_map<
Symbol, Symbol,
Value *, Value *,
std::hash<Symbol>, std::hash<Symbol>,

View file

@ -57,7 +57,7 @@
namespace nix { namespace nix {
typedef std::unordered_map<PosIdx, DocComment> DocCommentMap; typedef boost::unordered_flat_map<PosIdx, DocComment, std::hash<PosIdx>> DocCommentMap;
Expr * parseExprFromBuf( Expr * parseExprFromBuf(
char * text, char * text,

View file

@ -18,6 +18,8 @@
#include "nix/util/sort.hh" #include "nix/util/sort.hh"
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include <boost/unordered/concurrent_flat_map.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <sys/types.h> #include <sys/types.h>
@ -1750,7 +1752,7 @@ static void derivationStrictInternal(EvalState & state, std::string_view drvName
read them later. */ read them later. */
{ {
auto h = hashDerivationModulo(*state.store, drv, false); auto h = hashDerivationModulo(*state.store, drv, false);
drvHashes.lock()->insert_or_assign(drvPath, h); drvHashes.insert_or_assign(drvPath, std::move(h));
} }
auto result = state.buildBindings(1 + drv.outputs.size()); auto result = state.buildBindings(1 + drv.outputs.size());
@ -4027,7 +4029,7 @@ static void prim_groupBy(EvalState & state, const PosIdx pos, Value ** args, Val
auto name = state.forceStringNoCtx( auto name = state.forceStringNoCtx(
res, pos, "while evaluating the return value of the grouping function passed to builtins.groupBy"); res, pos, "while evaluating the return value of the grouping function passed to builtins.groupBy");
auto sym = state.symbols.create(name); auto sym = state.symbols.create(name);
auto vector = attrs.try_emplace(sym, ValueVector()).first; auto vector = attrs.try_emplace<ValueVector>(sym, {}).first;
vector->second.push_back(vElem); vector->second.push_back(vElem);
} }
@ -4562,27 +4564,21 @@ static RegisterPrimOp primop_convertHash({
struct RegexCache struct RegexCache
{ {
struct State boost::concurrent_flat_map<std::string, std::regex, StringViewHash, std::equal_to<>> cache;
{
std::unordered_map<std::string, std::regex, StringViewHash, std::equal_to<>> cache;
};
Sync<State> state_;
std::regex get(std::string_view re) std::regex get(std::string_view re)
{ {
auto state(state_.lock()); std::regex regex;
auto it = state->cache.find(re);
if (it != state->cache.end())
return it->second;
/* No std::regex constructor overload from std::string_view, but can be constructed /* No std::regex constructor overload from std::string_view, but can be constructed
from a pointer + size or an iterator range. */ from a pointer + size or an iterator range. */
return state->cache cache.try_emplace_and_cvisit(
.emplace( re,
std::piecewise_construct, /*s=*/re.data(),
std::forward_as_tuple(re), /*count=*/re.size(),
std::forward_as_tuple(/*s=*/re.data(), /*count=*/re.size(), std::regex::extended)) std::regex::extended,
.first->second; [&regex](const auto & kv) { regex = kv.second; },
[&regex](const auto & kv) { regex = kv.second; });
return regex;
} }
}; };
@ -4826,7 +4822,7 @@ static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value ** ar
from.emplace_back(state.forceString( from.emplace_back(state.forceString(
*elem, pos, "while evaluating one of the strings to replace passed to builtins.replaceStrings")); *elem, pos, "while evaluating one of the strings to replace passed to builtins.replaceStrings"));
std::unordered_map<size_t, std::string_view> cache; boost::unordered_flat_map<size_t, std::string_view> cache;
auto to = args[1]->listView(); auto to = args[1]->listView();
NixStringContext context; NixStringContext context;

View file

@ -1,5 +1,4 @@
#include <limits> #include <limits>
#include <unordered_set>
#include <sstream> #include <sstream>
#include "nix/expr/print.hh" #include "nix/expr/print.hh"
@ -10,6 +9,8 @@
#include "nix/util/english.hh" #include "nix/util/english.hh"
#include "nix/expr/eval.hh" #include "nix/expr/eval.hh"
#include <boost/unordered/unordered_flat_set.hpp>
namespace nix { namespace nix {
void printElided( void printElided(
@ -81,7 +82,7 @@ std::ostream & printLiteralBool(std::ostream & str, bool boolean)
// For example `or' doesn't need to be quoted. // For example `or' doesn't need to be quoted.
bool isReservedKeyword(const std::string_view str) bool isReservedKeyword(const std::string_view str)
{ {
static const std::unordered_set<std::string_view> reservedKeywords = { static const boost::unordered_flat_set<std::string_view> reservedKeywords = {
"if", "then", "else", "assert", "with", "let", "in", "rec", "inherit"}; "if", "then", "else", "assert", "with", "let", "in", "rec", "inherit"};
return reservedKeywords.contains(str); return reservedKeywords.contains(str);
} }

View file

@ -1,5 +1,7 @@
#include "nix/fetchers/filtering-source-accessor.hh" #include "nix/fetchers/filtering-source-accessor.hh"
#include <boost/unordered/unordered_flat_set.hpp>
namespace nix { namespace nix {
std::optional<std::filesystem::path> FilteringSourceAccessor::getPhysicalPath(const CanonPath & path) std::optional<std::filesystem::path> FilteringSourceAccessor::getPhysicalPath(const CanonPath & path)
@ -57,12 +59,12 @@ void FilteringSourceAccessor::checkAccess(const CanonPath & path)
struct AllowListSourceAccessorImpl : AllowListSourceAccessor struct AllowListSourceAccessorImpl : AllowListSourceAccessor
{ {
std::set<CanonPath> allowedPrefixes; std::set<CanonPath> allowedPrefixes;
std::unordered_set<CanonPath> allowedPaths; boost::unordered_flat_set<CanonPath, std::hash<CanonPath>> allowedPaths;
AllowListSourceAccessorImpl( AllowListSourceAccessorImpl(
ref<SourceAccessor> next, ref<SourceAccessor> next,
std::set<CanonPath> && allowedPrefixes, std::set<CanonPath> && allowedPrefixes,
std::unordered_set<CanonPath> && allowedPaths, boost::unordered_flat_set<CanonPath, std::hash<CanonPath>> && allowedPaths,
MakeNotAllowedError && makeNotAllowedError) MakeNotAllowedError && makeNotAllowedError)
: AllowListSourceAccessor(SourcePath(next), std::move(makeNotAllowedError)) : AllowListSourceAccessor(SourcePath(next), std::move(makeNotAllowedError))
, allowedPrefixes(std::move(allowedPrefixes)) , allowedPrefixes(std::move(allowedPrefixes))
@ -84,7 +86,7 @@ struct AllowListSourceAccessorImpl : AllowListSourceAccessor
ref<AllowListSourceAccessor> AllowListSourceAccessor::create( ref<AllowListSourceAccessor> AllowListSourceAccessor::create(
ref<SourceAccessor> next, ref<SourceAccessor> next,
std::set<CanonPath> && allowedPrefixes, std::set<CanonPath> && allowedPrefixes,
std::unordered_set<CanonPath> && allowedPaths, boost::unordered_flat_set<CanonPath, std::hash<CanonPath>> && allowedPaths,
MakeNotAllowedError && makeNotAllowedError) MakeNotAllowedError && makeNotAllowedError)
{ {
return make_ref<AllowListSourceAccessorImpl>( return make_ref<AllowListSourceAccessorImpl>(

View file

@ -30,8 +30,9 @@
#include <git2/sys/mempack.h> #include <git2/sys/mempack.h>
#include <git2/tree.h> #include <git2/tree.h>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_flat_set.hpp>
#include <iostream> #include <iostream>
#include <unordered_set>
#include <queue> #include <queue>
#include <regex> #include <regex>
#include <span> #include <span>
@ -315,7 +316,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
uint64_t getRevCount(const Hash & rev) override uint64_t getRevCount(const Hash & rev) override
{ {
std::unordered_set<git_oid> done; boost::unordered_flat_set<git_oid, std::hash<git_oid>> done;
std::queue<Commit> todo; std::queue<Commit> todo;
todo.push(peelObject<Commit>(lookupObject(*this, hashToOID(rev)).get(), GIT_OBJECT_COMMIT)); todo.push(peelObject<Commit>(lookupObject(*this, hashToOID(rev)).get(), GIT_OBJECT_COMMIT));
@ -569,7 +570,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
void verifyCommit(const Hash & rev, const std::vector<fetchers::PublicKey> & publicKeys) override void verifyCommit(const Hash & rev, const std::vector<fetchers::PublicKey> & publicKeys) override
{ {
// Map of SSH key types to their internal OpenSSH representations // Map of SSH key types to their internal OpenSSH representations
static const std::unordered_map<std::string_view, std::string_view> keyTypeMap = { static const boost::unordered_flat_map<std::string_view, std::string_view> keyTypeMap = {
{"ssh-dsa", "ssh-dsa"}, {"ssh-dsa", "ssh-dsa"},
{"ssh-ecdsa", "ssh-ecdsa"}, {"ssh-ecdsa", "ssh-ecdsa"},
{"ssh-ecdsa-sk", "sk-ecdsa-sha2-nistp256@openssh.com"}, {"ssh-ecdsa-sk", "sk-ecdsa-sha2-nistp256@openssh.com"},
@ -816,7 +817,7 @@ struct GitSourceAccessor : SourceAccessor
return toHash(*git_tree_entry_id(entry)); return toHash(*git_tree_entry_id(entry));
} }
std::unordered_map<CanonPath, TreeEntry> lookupCache; boost::unordered_flat_map<CanonPath, TreeEntry, std::hash<CanonPath>> lookupCache;
/* Recursively look up 'path' relative to the root. */ /* Recursively look up 'path' relative to the root. */
git_tree_entry * lookup(State & state, const CanonPath & path) git_tree_entry * lookup(State & state, const CanonPath & path)
@ -1253,7 +1254,7 @@ GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllow
makeFSSourceAccessor(path), makeFSSourceAccessor(path),
std::set<CanonPath>{wd.files}, std::set<CanonPath>{wd.files},
// Always allow access to the root, but not its children. // Always allow access to the root, but not its children.
std::unordered_set<CanonPath>{CanonPath::root}, boost::unordered_flat_set<CanonPath, std::hash<CanonPath>>{CanonPath::root},
std::move(makeNotAllowedError)) std::move(makeNotAllowedError))
.cast<SourceAccessor>(); .cast<SourceAccessor>();
if (exportIgnore) if (exportIgnore)

View file

@ -2,7 +2,7 @@
#include "nix/util/source-path.hh" #include "nix/util/source-path.hh"
#include <unordered_set> #include <boost/unordered/unordered_flat_set_fwd.hpp>
namespace nix { namespace nix {
@ -72,7 +72,7 @@ struct AllowListSourceAccessor : public FilteringSourceAccessor
static ref<AllowListSourceAccessor> create( static ref<AllowListSourceAccessor> create(
ref<SourceAccessor> next, ref<SourceAccessor> next,
std::set<CanonPath> && allowedPrefixes, std::set<CanonPath> && allowedPrefixes,
std::unordered_set<CanonPath> && allowedPaths, boost::unordered_flat_set<CanonPath, std::hash<CanonPath>> && allowedPaths,
MakeNotAllowedError && makeNotAllowedError); MakeNotAllowedError && makeNotAllowedError);
using FilteringSourceAccessor::FilteringSourceAccessor; using FilteringSourceAccessor::FilteringSourceAccessor;

View file

@ -1,5 +1,3 @@
#include <unordered_set>
#include "nix/fetchers/fetch-settings.hh" #include "nix/fetchers/fetch-settings.hh"
#include "nix/flake/settings.hh" #include "nix/flake/settings.hh"
#include "nix/flake/lockfile.hh" #include "nix/flake/lockfile.hh"
@ -9,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>
#include <boost/unordered/unordered_flat_set.hpp>
#include <iterator> #include <iterator>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
@ -162,7 +161,7 @@ std::pair<nlohmann::json, LockFile::KeyMap> LockFile::toJSON() const
{ {
nlohmann::json nodes; nlohmann::json nodes;
KeyMap nodeKeys; KeyMap nodeKeys;
std::unordered_set<std::string> keys; boost::unordered_flat_set<std::string> keys;
std::function<std::string(const std::string & key, ref<const Node> node)> dumpNode; std::function<std::string(const std::string & key, ref<const Node> node)> dumpNode;

View file

@ -11,6 +11,7 @@
#include "nix/util/json-utils.hh" #include "nix/util/json-utils.hh"
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include <boost/unordered/concurrent_flat_map.hpp>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
namespace nix { namespace nix {
@ -834,7 +835,7 @@ DerivationType BasicDerivation::type() const
throw Error("can't mix derivation output types"); throw Error("can't mix derivation output types");
} }
Sync<DrvHashes> drvHashes; DrvHashes drvHashes;
/* pathDerivationModulo and hashDerivationModulo are mutually recursive /* pathDerivationModulo and hashDerivationModulo are mutually recursive
*/ */
@ -844,16 +845,13 @@ Sync<DrvHashes> drvHashes;
*/ */
static const DrvHash pathDerivationModulo(Store & store, const StorePath & drvPath) static const DrvHash pathDerivationModulo(Store & store, const StorePath & drvPath)
{ {
{ std::optional<DrvHash> hash;
auto hashes = drvHashes.lock(); if (drvHashes.cvisit(drvPath, [&hash](const auto & kv) { hash.emplace(kv.second); })) {
auto h = hashes->find(drvPath); return *hash;
if (h != hashes->end()) {
return h->second;
}
} }
auto h = hashDerivationModulo(store, store.readInvalidDerivation(drvPath), false); auto h = hashDerivationModulo(store, store.readInvalidDerivation(drvPath), false);
// Cache it // Cache it
drvHashes.lock()->insert_or_assign(drvPath, h); drvHashes.insert_or_assign(drvPath, h);
return h; return h;
} }

View file

@ -1,6 +1,7 @@
#include "nix/store/derivations.hh" #include "nix/store/derivations.hh"
#include "nix/store/globals.hh" #include "nix/store/globals.hh"
#include "nix/store/local-store.hh" #include "nix/store/local-store.hh"
#include "nix/store/path.hh"
#include "nix/util/finally.hh" #include "nix/util/finally.hh"
#include "nix/util/unix-domain-socket.hh" #include "nix/util/unix-domain-socket.hh"
#include "nix/util/signals.hh" #include "nix/util/signals.hh"
@ -13,14 +14,10 @@
# include "nix/util/processes.hh" # include "nix/util/processes.hh"
#endif #endif
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_flat_set.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <functional>
#include <queue> #include <queue>
#include <algorithm>
#include <random>
#include <climits>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -314,7 +311,12 @@ Roots LocalStore::findRoots(bool censor)
/** /**
* Key is a mere string because cannot has path with macOS's libc++ * Key is a mere string because cannot has path with macOS's libc++
*/ */
typedef std::unordered_map<std::string, std::unordered_set<std::string>> UncheckedRoots; typedef boost::unordered_flat_map<
std::string,
boost::unordered_flat_set<std::string, StringViewHash, std::equal_to<>>,
StringViewHash,
std::equal_to<>>
UncheckedRoots;
static void readProcLink(const std::filesystem::path & file, UncheckedRoots & roots) static void readProcLink(const std::filesystem::path & file, UncheckedRoots & roots)
{ {
@ -328,7 +330,7 @@ static void readProcLink(const std::filesystem::path & file, UncheckedRoots & ro
throw; throw;
} }
if (buf.is_absolute()) if (buf.is_absolute())
roots[buf.string()].emplace(file.string()); roots[buf].emplace(file.string());
} }
static std::string quoteRegexChars(const std::string & raw) static std::string quoteRegexChars(const std::string & raw)
@ -463,13 +465,13 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
bool gcKeepOutputs = settings.gcKeepOutputs; bool gcKeepOutputs = settings.gcKeepOutputs;
bool gcKeepDerivations = settings.gcKeepDerivations; bool gcKeepDerivations = settings.gcKeepDerivations;
std::unordered_set<StorePath> roots, dead, alive; boost::unordered_flat_set<StorePath, std::hash<StorePath>> roots, dead, alive;
struct Shared struct Shared
{ {
// The temp roots only store the hash part to make it easier to // The temp roots only store the hash part to make it easier to
// ignore suffixes like '.lock', '.chroot' and '.check'. // ignore suffixes like '.lock', '.chroot' and '.check'.
std::unordered_set<std::string> tempRoots; boost::unordered_flat_set<std::string, StringViewHash, std::equal_to<>> tempRoots;
// Hash part of the store path currently being deleted, if // Hash part of the store path currently being deleted, if
// any. // any.
@ -578,9 +580,9 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
auto storePath = maybeParseStorePath(path); auto storePath = maybeParseStorePath(path);
if (storePath) { if (storePath) {
debug("got new GC root '%s'", path); debug("got new GC root '%s'", path);
auto hashPart = std::string(storePath->hashPart()); auto hashPart = storePath->hashPart();
auto shared(_shared.lock()); auto shared(_shared.lock());
shared->tempRoots.insert(hashPart); shared->tempRoots.emplace(hashPart);
/* If this path is currently being /* If this path is currently being
deleted, then we have to wait until deleted, then we have to wait until
deletion is finished to ensure that deletion is finished to ensure that
@ -632,7 +634,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
Roots tempRoots; Roots tempRoots;
findTempRoots(tempRoots, true); findTempRoots(tempRoots, true);
for (auto & root : tempRoots) { for (auto & root : tempRoots) {
_shared.lock()->tempRoots.insert(std::string(root.first.hashPart())); _shared.lock()->tempRoots.emplace(root.first.hashPart());
roots.insert(root.first); roots.insert(root.first);
} }
@ -672,7 +674,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
} }
}; };
std::unordered_map<StorePath, StorePathSet> referrersCache; boost::unordered_flat_map<StorePath, StorePathSet, std::hash<StorePath>> referrersCache;
/* Helper function that visits all paths reachable from `start` /* Helper function that visits all paths reachable from `start`
via the referrers edges and optionally derivers and derivation via the referrers edges and optionally derivers and derivation
@ -739,7 +741,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
return; return;
{ {
auto hashPart = std::string(path->hashPart()); auto hashPart = path->hashPart();
auto shared(_shared.lock()); auto shared(_shared.lock());
if (shared->tempRoots.count(hashPart)) { if (shared->tempRoots.count(hashPart)) {
debug("cannot delete '%s' because it's a temporary root", printStorePath(*path)); debug("cannot delete '%s' because it's a temporary root", printStorePath(*path));

View file

@ -11,7 +11,7 @@
#include "nix/util/sync.hh" #include "nix/util/sync.hh"
#include "nix/util/variant-wrapper.hh" #include "nix/util/variant-wrapper.hh"
#include <map> #include <boost/unordered/concurrent_flat_map_fwd.hpp>
#include <variant> #include <variant>
namespace nix { namespace nix {
@ -507,13 +507,23 @@ DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOut
*/ */
std::map<std::string, Hash> staticOutputHashes(Store & store, const Derivation & drv); std::map<std::string, Hash> 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<std::string_view>{}(path.to_string());
}
};
/** /**
* Memoisation of hashDerivationModulo(). * Memoisation of hashDerivationModulo().
*/ */
typedef std::map<StorePath, DrvHash> DrvHashes; typedef boost::concurrent_flat_map<StorePath, DrvHash, DrvHashFct> DrvHashes;
// FIXME: global, though at least thread-safe. // FIXME: global, though at least thread-safe.
extern Sync<DrvHashes> drvHashes; extern DrvHashes drvHashes;
struct Source; struct Source;
struct Sink; struct Sink;

View file

@ -1,13 +1,17 @@
#pragma once #pragma once
///@file ///@file
#include <unordered_set>
#include "nix/store/store-api.hh" #include "nix/store/store-api.hh"
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_flat_set.hpp>
namespace nix { namespace nix {
typedef std::unordered_map<StorePath, std::unordered_set<std::string>> Roots; typedef boost::unordered_flat_map<
StorePath,
boost::unordered_flat_set<std::string, StringViewHash, std::equal_to<>>,
std::hash<StorePath>>
Roots;
struct GCOptions struct GCOptions
{ {

View file

@ -11,7 +11,7 @@
#include <chrono> #include <chrono>
#include <future> #include <future>
#include <string> #include <string>
#include <unordered_set> #include <boost/unordered/unordered_flat_set.hpp>
namespace nix { namespace nix {
@ -442,7 +442,7 @@ private:
std::pair<std::filesystem::path, AutoCloseFD> createTempDirInStore(); std::pair<std::filesystem::path, AutoCloseFD> createTempDirInStore();
typedef std::unordered_set<ino_t> InodeHash; typedef boost::unordered_flat_set<ino_t> InodeHash;
InodeHash loadInodeHash(); InodeHash loadInodeHash();
Strings readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash); Strings readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash);

View file

@ -1,5 +1,3 @@
#include <unordered_set>
#include "nix/store/derivations.hh" #include "nix/store/derivations.hh"
#include "nix/store/parsed-derivations.hh" #include "nix/store/parsed-derivations.hh"
#include "nix/store/derivation-options.hh" #include "nix/store/derivation-options.hh"
@ -13,6 +11,8 @@
#include "nix/store/filetransfer.hh" #include "nix/store/filetransfer.hh"
#include "nix/util/strings.hh" #include "nix/util/strings.hh"
#include <boost/unordered/unordered_flat_set.hpp>
namespace nix { namespace nix {
void Store::computeFSClosure( void Store::computeFSClosure(
@ -106,7 +106,7 @@ MissingPaths Store::queryMissing(const std::vector<DerivedPath> & targets)
struct State struct State
{ {
std::unordered_set<std::string> done; boost::unordered_flat_set<std::string> done;
MissingPaths res; MissingPaths res;
}; };

View file

@ -258,7 +258,7 @@ public:
*/ */
std::string makeRelative(const CanonPath & path) const; std::string makeRelative(const CanonPath & path) const;
friend class std::hash<CanonPath>; friend struct std::hash<CanonPath>;
}; };
std::ostream & operator<<(std::ostream & stream, const CanonPath & path); std::ostream & operator<<(std::ostream & stream, const CanonPath & path);
@ -268,6 +268,8 @@ std::ostream & operator<<(std::ostream & stream, const CanonPath & path);
template<> template<>
struct std::hash<nix::CanonPath> struct std::hash<nix::CanonPath>
{ {
using is_avalanching = std::true_type;
std::size_t operator()(const nix::CanonPath & s) const noexcept std::size_t operator()(const nix::CanonPath & s) const noexcept
{ {
return std::hash<std::string>{}(s.path); return std::hash<std::string>{}(s.path);

View file

@ -4,10 +4,10 @@
#include "nix/util/file-system.hh" #include "nix/util/file-system.hh"
#include "nix/util/finally.hh" #include "nix/util/finally.hh"
#include <boost/unordered/unordered_flat_set.hpp>
#include <chrono> #include <chrono>
#include <cmath> #include <cmath>
#include <regex> #include <regex>
#include <unordered_set>
#include <thread> #include <thread>
#include <dirent.h> #include <dirent.h>
@ -76,7 +76,7 @@ static CgroupStats destroyCgroup(const std::filesystem::path & cgroup, bool retu
int round = 1; int round = 1;
std::unordered_set<pid_t> pidsShown; boost::unordered_flat_set<pid_t> pidsShown;
while (true) { while (true) {
auto pids = tokenizeString<std::vector<std::string>>(readFile(procsFile)); auto pids = tokenizeString<std::vector<std::string>>(readFile(procsFile));

View file

@ -104,7 +104,7 @@ std::optional<struct stat> PosixSourceAccessor::cachedLstat(const CanonPath & pa
if (cache.size() >= 16384) if (cache.size() >= 16384)
cache.clear(); cache.clear();
cache.emplace(absPath, st); cache.emplace(std::move(absPath), st);
return st; return st;
} }

View file

@ -71,7 +71,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
auto outPaths = auto outPaths =
Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables); Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
std::unordered_set<StorePath> done; boost::unordered_flat_set<StorePath, std::hash<StorePath>> done;
std::queue<StorePath> todo; std::queue<StorePath> todo;
for (auto & path : outPaths) for (auto & path : outPaths)
todo.push(path); todo.push(path);