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

libexpr: replace std::unordered_* types by faster boost hash maps

This commit is contained in:
Philipp Otterbein 2025-08-05 00:55:32 +02:00 committed by Jörg Thalheim
parent c0fd9146d6
commit 4f8c50fb77
6 changed files with 42 additions and 45 deletions

View file

@ -1090,7 +1090,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();
} }
@ -2375,10 +2377,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),
@ -2386,15 +2387,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
{ {
@ -395,7 +397,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
{ {
@ -438,12 +440,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>,
@ -455,7 +457,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>,
@ -468,11 +470,11 @@ 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>> lookupPathResolved;
/** /**
* Cache used by prim_match(). * Cache used by prim_match().
@ -746,7 +748,7 @@ 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>, std::hash<std::string>,
@ -1017,10 +1019,10 @@ private:
bool countCalls; bool countCalls;
typedef std::map<std::string, size_t> PrimOpCalls; typedef boost::unordered_flat_map<std::string, size_t> 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. */
@ -1028,7 +1030,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 {
@ -1166,7 +1167,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,19 @@ 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(re,
.emplace( /*s=*/re.data(), /*count=*/re.size(), std::regex::extended,
std::piecewise_construct, [&regex](const auto & kv) { regex = kv.second; },
std::forward_as_tuple(re), [&regex](const auto & kv) { regex = kv.second; }
std::forward_as_tuple(/*s=*/re.data(), /*count=*/re.size(), std::regex::extended)) );
.first->second; return regex;
} }
}; };
@ -4826,7 +4820,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;