Skip to content

Commit

Permalink
Merge pull request NixOS#11092 from DeterminateSystems/hash-SourcePath
Browse files Browse the repository at this point in the history
Use std::unordered_map for the EvalState caches
  • Loading branch information
edolstra authored Jul 16, 2024
2 parents 4bbadba + 550b347 commit 9c6678d
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 8 deletions.
6 changes: 3 additions & 3 deletions src/libexpr/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,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
Expand All @@ -1084,8 +1084,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);
}


Expand Down
10 changes: 5 additions & 5 deletions src/libexpr/eval.hh
Original file line number Diff line number Diff line change
Expand Up @@ -309,25 +309,25 @@ private:

/* Cache for calls to addToStore(); maps source paths to the store
paths. */
Sync<std::map<SourcePath, StorePath>> srcToStore;
Sync<std::unordered_map<SourcePath, StorePath>> srcToStore;

/**
* A cache from path names to parse trees.
*/
#if HAVE_BOEHMGC
typedef std::map<SourcePath, Expr *, std::less<SourcePath>, traceable_allocator<std::pair<const SourcePath, Expr *>>> FileParseCache;
typedef std::unordered_map<SourcePath, Expr *, std::hash<SourcePath>, std::equal_to<SourcePath>, traceable_allocator<std::pair<const SourcePath, Expr *>>> FileParseCache;
#else
typedef std::map<SourcePath, Expr *> FileParseCache;
typedef std::unordered_map<SourcePath, Expr *> FileParseCache;
#endif
FileParseCache fileParseCache;

/**
* A cache from path names to values.
*/
#if HAVE_BOEHMGC
typedef std::map<SourcePath, Value, std::less<SourcePath>, traceable_allocator<std::pair<const SourcePath, Value>>> FileEvalCache;
typedef std::unordered_map<SourcePath, Value, std::hash<SourcePath>, std::equal_to<SourcePath>, traceable_allocator<std::pair<const SourcePath, Value>>> FileEvalCache;
#else
typedef std::map<SourcePath, Value> FileEvalCache;
typedef std::unordered_map<SourcePath, Value> FileEvalCache;
#endif
FileEvalCache fileEvalCache;

Expand Down
15 changes: 15 additions & 0 deletions src/libutil/source-path.hh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "canon-path.hh"
#include "source-accessor.hh"

#include <boost/functional/hash.hpp> // for boost::hash_combine

namespace nix {

/**
Expand Down Expand Up @@ -114,8 +116,21 @@ struct SourcePath
{
return {accessor, accessor->resolveSymlinks(path, mode)};
}

friend class std::hash<nix::SourcePath>;
};

std::ostream & operator << (std::ostream & str, const SourcePath & path);

}

template<>
struct std::hash<nix::SourcePath>
{
std::size_t operator()(const nix::SourcePath & s) const noexcept
{
std::size_t hash = 0;
hash_combine(hash, s.accessor->number, s.path);
return hash;
}
};
14 changes: 14 additions & 0 deletions src/libutil/util.hh
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,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 <typename T, typename... Rest>
inline void hash_combine(std::size_t & seed, const T & v, Rest... rest)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
hash_combine(seed, rest...);
}

}

0 comments on commit 9c6678d

Please sign in to comment.