From cdc23b67a66ff3daf495b8d1e5b199095e01bac9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 6 Jun 2024 19:12:36 +0200 Subject: [PATCH 1/2] Provide std::hash --- src/libexpr/eval.cc | 6 +++--- src/libexpr/eval.hh | 10 +++++----- src/libutil/source-path.hh | 11 +++++++++++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 72ae159cb..584828a09 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1011,7 +1011,7 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial) if (!e) e = parseExprFromFile(resolvedPath); - fileParseCache[resolvedPath] = e; + fileParseCache.emplace(resolvedPath, e); try { auto dts = debugRepl @@ -1034,8 +1034,8 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial) throw; } - fileEvalCache[resolvedPath] = v; - if (path != resolvedPath) fileEvalCache[path] = v; + fileEvalCache.emplace(resolvedPath, v); + if (path != resolvedPath) fileEvalCache.emplace(path, v); } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 7dbf61c5d..d368bc049 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -307,15 +307,15 @@ private: /* Cache for calls to addToStore(); maps source paths to the store paths. */ - Sync> srcToStore; + Sync> srcToStore; /** * A cache from path names to parse trees. */ #if HAVE_BOEHMGC - typedef std::map, traceable_allocator>> FileParseCache; + typedef std::unordered_map, std::equal_to, traceable_allocator>> FileParseCache; #else - typedef std::map FileParseCache; + typedef std::unordered_map FileParseCache; #endif FileParseCache fileParseCache; @@ -323,9 +323,9 @@ private: * A cache from path names to values. */ #if HAVE_BOEHMGC - typedef std::map, traceable_allocator>> FileEvalCache; + typedef std::unordered_map, std::equal_to, traceable_allocator>> FileEvalCache; #else - typedef std::map FileEvalCache; + typedef std::unordered_map FileEvalCache; #endif FileEvalCache fileEvalCache; diff --git a/src/libutil/source-path.hh b/src/libutil/source-path.hh index 83ec6295d..941744127 100644 --- a/src/libutil/source-path.hh +++ b/src/libutil/source-path.hh @@ -115,8 +115,19 @@ struct SourcePath { return {accessor, accessor->resolveSymlinks(path, mode)}; } + + friend class std::hash; }; std::ostream & operator << (std::ostream & str, const SourcePath & path); } + +template<> +struct std::hash +{ + std::size_t operator()(const nix::SourcePath & s) const noexcept + { + return std::hash{}(s.path); + } +}; From 550b3479cf066b9e5a435d1cb42240f88021b31f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jul 2024 15:46:30 +0200 Subject: [PATCH 2/2] Include the accessor in the SourcePath hash --- src/libutil/source-path.hh | 6 +++++- src/libutil/util.hh | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/libutil/source-path.hh b/src/libutil/source-path.hh index 941744127..d310231a7 100644 --- a/src/libutil/source-path.hh +++ b/src/libutil/source-path.hh @@ -9,6 +9,8 @@ #include "canon-path.hh" #include "source-accessor.hh" +#include // for boost::hash_combine + namespace nix { /** @@ -128,6 +130,8 @@ struct std::hash { std::size_t operator()(const nix::SourcePath & s) const noexcept { - return std::hash{}(s.path); + std::size_t hash = 0; + hash_combine(hash, s.accessor->number, s.path); + return hash; } }; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 23682ff7c..dd1139843 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -360,4 +360,18 @@ inline std::string operator + (std::string_view s1, const char * s2) return s; } +/** + * hash_combine() from Boost. Hash several hashable values together + * into a single hash. + */ +inline void hash_combine(std::size_t & seed) { } + +template +inline void hash_combine(std::size_t & seed, const T & v, Rest... rest) +{ + std::hash hasher; + seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); + hash_combine(seed, rest...); +} + }