1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-15 15:02:42 +01:00

LocalStore::State: Put behind a ref to reduce false sharing

This commit is contained in:
Eelco Dolstra 2025-09-04 12:08:25 +02:00
parent 9ff427d7ba
commit e791ede495
3 changed files with 25 additions and 37 deletions

View file

@ -931,7 +931,7 @@ void LocalStore::autoGC(bool sync)
std::shared_future<void> future; std::shared_future<void> future;
{ {
auto state(_state.lock()); auto state(_state->lock());
if (state->gcRunning) { if (state->gcRunning) {
future = state->gcFuture; future = state->gcFuture;
@ -964,7 +964,7 @@ void LocalStore::autoGC(bool sync)
/* Wake up any threads waiting for the auto-GC to finish. */ /* Wake up any threads waiting for the auto-GC to finish. */
Finally wakeup([&]() { Finally wakeup([&]() {
auto state(_state.lock()); auto state(_state->lock());
state->gcRunning = false; state->gcRunning = false;
state->lastGCCheck = std::chrono::steady_clock::now(); state->lastGCCheck = std::chrono::steady_clock::now();
promise.set_value(); promise.set_value();
@ -979,7 +979,7 @@ void LocalStore::autoGC(bool sync)
collectGarbage(options, results); collectGarbage(options, results);
_state.lock()->availAfterGC = getAvail(); _state->lock()->availAfterGC = getAvail();
} catch (...) { } catch (...) {
// FIXME: we could propagate the exception to the // FIXME: we could propagate the exception to the

View file

@ -174,7 +174,7 @@ private:
std::unique_ptr<PublicKeys> publicKeys; std::unique_ptr<PublicKeys> publicKeys;
}; };
Sync<State> _state; ref<Sync<State>> _state;
public: public:

View file

@ -118,6 +118,7 @@ LocalStore::LocalStore(ref<const Config> config)
: Store{*config} : Store{*config}
, LocalFSStore{*config} , LocalFSStore{*config}
, config{config} , config{config}
, _state(make_ref<Sync<State>>())
, dbDir(config->stateDir + "/db") , dbDir(config->stateDir + "/db")
, linksDir(config->realStoreDir + "/.links") , linksDir(config->realStoreDir + "/.links")
, reservedPath(dbDir + "/reserved") , reservedPath(dbDir + "/reserved")
@ -125,7 +126,7 @@ LocalStore::LocalStore(ref<const Config> config)
, tempRootsDir(config->stateDir + "/temproots") , tempRootsDir(config->stateDir + "/temproots")
, fnTempRoots(fmt("%s/%d", tempRootsDir, getpid())) , fnTempRoots(fmt("%s/%d", tempRootsDir, getpid()))
{ {
auto state(_state.lock()); auto state(_state->lock());
state->stmts = std::make_unique<State::Stmts>(); state->stmts = std::make_unique<State::Stmts>();
/* Create missing state directories if they don't already exist. */ /* Create missing state directories if they don't already exist. */
@ -433,7 +434,7 @@ LocalStore::~LocalStore()
std::shared_future<void> future; std::shared_future<void> future;
{ {
auto state(_state.lock()); auto state(_state->lock());
if (state->gcRunning) if (state->gcRunning)
future = state->gcFuture; future = state->gcFuture;
} }
@ -629,7 +630,7 @@ void LocalStore::registerDrvOutput(const Realisation & info)
{ {
experimentalFeatureSettings.require(Xp::CaDerivations); experimentalFeatureSettings.require(Xp::CaDerivations);
retrySQLite<void>([&]() { retrySQLite<void>([&]() {
auto state(_state.lock()); auto state(_state->lock());
if (auto oldR = queryRealisation_(*state, info.id)) { if (auto oldR = queryRealisation_(*state, info.id)) {
if (info.isCompatibleWith(*oldR)) { if (info.isCompatibleWith(*oldR)) {
auto combinedSignatures = oldR->signatures; auto combinedSignatures = oldR->signatures;
@ -736,8 +737,7 @@ void LocalStore::queryPathInfoUncached(
{ {
try { try {
callback(retrySQLite<std::shared_ptr<const ValidPathInfo>>([&]() { callback(retrySQLite<std::shared_ptr<const ValidPathInfo>>([&]() {
auto state(_state.lock()); return queryPathInfoInternal(*_state->lock(), path);
return queryPathInfoInternal(*state, path);
})); }));
} catch (...) { } catch (...) {
@ -819,10 +819,7 @@ bool LocalStore::isValidPath_(State & state, const StorePath & path)
bool LocalStore::isValidPathUncached(const StorePath & path) bool LocalStore::isValidPathUncached(const StorePath & path)
{ {
return retrySQLite<bool>([&]() { return retrySQLite<bool>([&]() { return isValidPath_(*_state->lock(), path); });
auto state(_state.lock());
return isValidPath_(*state, path);
});
} }
StorePathSet LocalStore::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute) StorePathSet LocalStore::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute)
@ -837,7 +834,7 @@ StorePathSet LocalStore::queryValidPaths(const StorePathSet & paths, SubstituteF
StorePathSet LocalStore::queryAllValidPaths() StorePathSet LocalStore::queryAllValidPaths()
{ {
return retrySQLite<StorePathSet>([&]() { return retrySQLite<StorePathSet>([&]() {
auto state(_state.lock()); auto state(_state->lock());
auto use(state->stmts->QueryValidPaths.use()); auto use(state->stmts->QueryValidPaths.use());
StorePathSet res; StorePathSet res;
while (use.next()) while (use.next())
@ -856,16 +853,13 @@ void LocalStore::queryReferrers(State & state, const StorePath & path, StorePath
void LocalStore::queryReferrers(const StorePath & path, StorePathSet & referrers) void LocalStore::queryReferrers(const StorePath & path, StorePathSet & referrers)
{ {
return retrySQLite<void>([&]() { return retrySQLite<void>([&]() { queryReferrers(*_state->lock(), path, referrers); });
auto state(_state.lock());
queryReferrers(*state, path, referrers);
});
} }
StorePathSet LocalStore::queryValidDerivers(const StorePath & path) StorePathSet LocalStore::queryValidDerivers(const StorePath & path)
{ {
return retrySQLite<StorePathSet>([&]() { return retrySQLite<StorePathSet>([&]() {
auto state(_state.lock()); auto state(_state->lock());
auto useQueryValidDerivers(state->stmts->QueryValidDerivers.use()(printStorePath(path))); auto useQueryValidDerivers(state->stmts->QueryValidDerivers.use()(printStorePath(path)));
@ -881,7 +875,7 @@ std::map<std::string, std::optional<StorePath>>
LocalStore::queryStaticPartialDerivationOutputMap(const StorePath & path) LocalStore::queryStaticPartialDerivationOutputMap(const StorePath & path)
{ {
return retrySQLite<std::map<std::string, std::optional<StorePath>>>([&]() { return retrySQLite<std::map<std::string, std::optional<StorePath>>>([&]() {
auto state(_state.lock()); auto state(_state->lock());
std::map<std::string, std::optional<StorePath>> outputs; std::map<std::string, std::optional<StorePath>> outputs;
uint64_t drvId; uint64_t drvId;
drvId = queryValidPathId(*state, path); drvId = queryValidPathId(*state, path);
@ -901,7 +895,7 @@ std::optional<StorePath> LocalStore::queryPathFromHashPart(const std::string & h
Path prefix = storeDir + "/" + hashPart; Path prefix = storeDir + "/" + hashPart;
return retrySQLite<std::optional<StorePath>>([&]() -> std::optional<StorePath> { return retrySQLite<std::optional<StorePath>>([&]() -> std::optional<StorePath> {
auto state(_state.lock()); auto state(_state->lock());
auto useQueryPathFromHashPart(state->stmts->QueryPathFromHashPart.use()(prefix)); auto useQueryPathFromHashPart(state->stmts->QueryPathFromHashPart.use()(prefix));
@ -966,7 +960,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
#endif #endif
return retrySQLite<void>([&]() { return retrySQLite<void>([&]() {
auto state(_state.lock()); auto state(_state->lock());
SQLiteTxn txn(state->db); SQLiteTxn txn(state->db);
StorePathSet paths; StorePathSet paths;
@ -1036,7 +1030,7 @@ void LocalStore::invalidatePath(State & state, const StorePath & path)
const PublicKeys & LocalStore::getPublicKeys() const PublicKeys & LocalStore::getPublicKeys()
{ {
auto state(_state.lock()); auto state(_state->lock());
if (!state->publicKeys) if (!state->publicKeys)
state->publicKeys = std::make_unique<PublicKeys>(getDefaultPublicKeys()); state->publicKeys = std::make_unique<PublicKeys>(getDefaultPublicKeys());
return *state->publicKeys; return *state->publicKeys;
@ -1359,7 +1353,7 @@ std::pair<std::filesystem::path, AutoCloseFD> LocalStore::createTempDirInStore()
void LocalStore::invalidatePathChecked(const StorePath & path) void LocalStore::invalidatePathChecked(const StorePath & path)
{ {
retrySQLite<void>([&]() { retrySQLite<void>([&]() {
auto state(_state.lock()); auto state(_state->lock());
SQLiteTxn txn(state->db); SQLiteTxn txn(state->db);
@ -1459,10 +1453,8 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
update = true; update = true;
} }
if (update) { if (update)
auto state(_state.lock()); updatePathInfo(*_state->lock(), *info);
updatePathInfo(*state, *info);
}
} }
} catch (Error & e) { } catch (Error & e) {
@ -1549,8 +1541,7 @@ void LocalStore::verifyPath(
if (canInvalidate) { if (canInvalidate) {
printInfo("path '%s' disappeared, removing from database...", pathS); printInfo("path '%s' disappeared, removing from database...", pathS);
auto state(_state.lock()); invalidatePath(*_state->lock(), path);
invalidatePath(*state, path);
} else { } else {
printError("path '%s' disappeared, but it still has valid referrers!", pathS); printError("path '%s' disappeared, but it still has valid referrers!", pathS);
if (repair) if (repair)
@ -1582,14 +1573,13 @@ std::optional<TrustedFlag> LocalStore::isTrustedClient()
void LocalStore::vacuumDB() void LocalStore::vacuumDB()
{ {
auto state(_state.lock()); _state->lock()->db.exec("vacuum");
state->db.exec("vacuum");
} }
void LocalStore::addSignatures(const StorePath & storePath, const StringSet & sigs) void LocalStore::addSignatures(const StorePath & storePath, const StringSet & sigs)
{ {
retrySQLite<void>([&]() { retrySQLite<void>([&]() {
auto state(_state.lock()); auto state(_state->lock());
SQLiteTxn txn(state->db); SQLiteTxn txn(state->db);
@ -1651,10 +1641,8 @@ void LocalStore::queryRealisationUncached(
const DrvOutput & id, Callback<std::shared_ptr<const Realisation>> callback) noexcept const DrvOutput & id, Callback<std::shared_ptr<const Realisation>> callback) noexcept
{ {
try { try {
auto maybeRealisation = retrySQLite<std::optional<const Realisation>>([&]() { auto maybeRealisation =
auto state(_state.lock()); retrySQLite<std::optional<const Realisation>>([&]() { return queryRealisation_(*_state->lock(), id); });
return queryRealisation_(*state, id);
});
if (maybeRealisation) if (maybeRealisation)
callback(std::make_shared<const Realisation>(maybeRealisation.value())); callback(std::make_shared<const Realisation>(maybeRealisation.value()));
else else