40
40
41
41
#include < nlohmann/json.hpp>
42
42
#include < boost/container/small_vector.hpp>
43
+ #include < boost/unordered/concurrent_flat_map.hpp>
43
44
44
45
#ifndef _WIN32 // TODO use portable implementation
45
46
# include < sys/resource.h>
@@ -213,6 +214,27 @@ static Symbol getName(const AttrName & name, EvalState & state, Env & env)
213
214
214
215
static constexpr size_t BASE_ENV_SIZE = 128 ;
215
216
217
+ struct EvalState ::SrcToStore
218
+ {
219
+ boost::concurrent_flat_map<SourcePath, StorePath> inner;
220
+ };
221
+
222
+ struct EvalState ::ImportResolutionCache
223
+ {
224
+ boost::concurrent_flat_map<SourcePath, SourcePath> inner;
225
+ };
226
+
227
+ struct EvalState ::FileEvalCache
228
+ {
229
+ boost::concurrent_flat_map<
230
+ SourcePath,
231
+ Value *,
232
+ std::hash<SourcePath>,
233
+ std::equal_to<SourcePath>,
234
+ traceable_allocator<std::pair<const SourcePath, Value *>>>
235
+ inner;
236
+ };
237
+
216
238
EvalState::EvalState (
217
239
const LookupPath & lookupPathFromArguments,
218
240
ref<Store> store,
@@ -344,6 +366,9 @@ EvalState::EvalState(
344
366
, debugStop(false )
345
367
, trylevel(0 )
346
368
, asyncPathWriter(AsyncPathWriter::make(store))
369
+ , srcToStore(make_ref<SrcToStore>())
370
+ , importResolutionCache(make_ref<ImportResolutionCache>())
371
+ , fileEvalCache(make_ref<FileEvalCache>())
347
372
, regexCache(makeRegexCache())
348
373
#if NIX_USE_BOEHMGC
349
374
, baseEnvP(std::allocate_shared<Env *>(traceable_allocator<Env *>(), &allocEnv (BASE_ENV_SIZE)))
@@ -1168,29 +1193,31 @@ struct ExprParseFile : Expr
1168
1193
1169
1194
void EvalState::evalFile (const SourcePath & path, Value & v, bool mustBeTrivial)
1170
1195
{
1171
- auto resolvedPath = getOptional (* importResolutionCache. readLock () , path);
1196
+ auto resolvedPath = getConcurrent ( importResolutionCache-> inner , path);
1172
1197
1173
1198
if (!resolvedPath) {
1174
1199
resolvedPath = resolveExprPath (path);
1175
- importResolutionCache. lock ()-> emplace (path, *resolvedPath);
1200
+ importResolutionCache-> inner . emplace (path, *resolvedPath);
1176
1201
}
1177
1202
1178
- if (auto v2 = get (* fileEvalCache. readLock () , *resolvedPath)) {
1179
- forceValue (*const_cast <Value *>(v2) , noPos);
1180
- v = *v2;
1203
+ if (auto v2 = getConcurrent ( fileEvalCache-> inner , *resolvedPath)) {
1204
+ forceValue (**v2 , noPos);
1205
+ v = ** v2;
1181
1206
return ;
1182
1207
}
1183
1208
1184
1209
Value * vExpr;
1185
1210
ExprParseFile expr{*resolvedPath, mustBeTrivial};
1186
1211
1187
- {
1188
- auto cache (fileEvalCache.lock ());
1189
- auto [i, inserted] = cache->try_emplace (*resolvedPath);
1190
- if (inserted)
1191
- i->second .mkThunk (&baseEnv, &expr);
1192
- vExpr = &i->second ;
1193
- }
1212
+ fileEvalCache->inner .try_emplace_and_cvisit (
1213
+ *resolvedPath,
1214
+ nullptr ,
1215
+ [&](auto & i) {
1216
+ vExpr = allocValue ();
1217
+ vExpr->mkThunk (&baseEnv, &expr);
1218
+ i.second = vExpr;
1219
+ },
1220
+ [&](auto & i) { vExpr = i.second ; });
1194
1221
1195
1222
forceValue (*vExpr, noPos);
1196
1223
@@ -1199,7 +1226,7 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial)
1199
1226
1200
1227
void EvalState::resetFileCache ()
1201
1228
{
1202
- fileEvalCache. lock ()-> clear ();
1229
+ fileEvalCache-> inner . clear ();
1203
1230
inputCache->clear ();
1204
1231
}
1205
1232
@@ -2499,7 +2526,7 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat
2499
2526
if (nix::isDerivation (path.path .abs ()))
2500
2527
error<EvalError>(" file names are not allowed to end in '%1%'" , drvExtension).debugThrow ();
2501
2528
2502
- auto dstPathCached = get (* srcToStore. lock () , path);
2529
+ auto dstPathCached = getConcurrent ( srcToStore-> inner , path);
2503
2530
2504
2531
auto dstPath = dstPathCached ? *dstPathCached : [&]() {
2505
2532
auto dstPath = fetchToStore (
@@ -2512,7 +2539,7 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat
2512
2539
nullptr ,
2513
2540
repair);
2514
2541
allowPath (dstPath);
2515
- srcToStore. lock ()-> try_emplace (path, dstPath);
2542
+ srcToStore-> inner . try_emplace (path, dstPath);
2516
2543
printMsg (lvlChatty, " copied source '%1%' -> '%2%'" , path, store->printStorePath (dstPath));
2517
2544
return dstPath;
2518
2545
}();
0 commit comments