Remove TokenServer in preparation of making NAR copying O(1) memory
[?]
Jul 27, 2020, 12:57 PM
ZMICO7M6COWUZLYQ5MV374BQJLWROSTEORLTOINSU4UGB7TJKJTACDependencies
- [2]
EYIB6HA6Supress debug message - [3]
YSZQ3ORRFix build - [4]
BG6PEOB2Make the output size limit configurable - [5]
NSBNNM77Add hydra.conf option "nar_buffer_size" to configure memoryTokens limit - [6]
JPHDKOMJhydra-queue-runner: Keep some notification statistics - [7]
PLOZBRTRAdd command ‘hydra-queue-runner --status’ to show current status - [8]
ENXUSMSVMake concurrency more robust - [9]
7LB6QBXYKeep track of the number of build steps that are being built - [10]
EOO4EFWDUse a single BinaryCacheStore for all threads - [11]
BYVRA54QTemporarily disable machines on any exception, not just connection failures - [12]
GTUZLZRHAdd an S3-backed binary cache store - [13]
XLYHZUHTCache .narinfo lookups - [14]
FHVJYJFEUpload build logs to the binary cache - [15]
FJ5H26J6Fix building against nix master - [16]
YZAI5GQUImplement a database connection pool - [17]
4YCF3KBGConcurrent hydra-evaluator - [18]
SGFLU2VSUSER -> LOGNAME for consistency - [19]
B2L4T3X6Sync with Nix - [20]
2DNPZFPNStep cancellation: Don't use pthread_cancel() - [21]
IGLIPGT6Make maxLogSize configurable - [22]
GH4S4AWMRename file - [23]
DIEY5USNKeep better bytesReceived/bytesSent stats - [24]
BRAESISHWarn if PostgreSQL appears stalled - [25]
7KLHBDYAFix build - [26]
LSUX6IQRUpdate to latest nixUnstable - [27]
MB3TISH2Rate-limit the number of threads copying closures at the same time - [28]
U55WNIDPAbort unsupported build steps - [29]
BTSZJ7W2Quick hack to fix compilation - [30]
UVNTWTWGPrevent download of NARs we just uploaded - [31]
BUEWVH2MRemove signing parameter (nix#f435f82) - [32]
LVQXQIYAKill active build steps when builds are cancelled - [33]
NJXD2ABJAbort unsupported build steps - [34]
SL3WSRAChydra-queue-runner: Limit memory usage - [35]
IKJBYIGYUpdate to reflect BinaryCacheStore changes - [36]
3YSJ3LYKRemove finally.hh - [37]
N4IROACVMove buildRemote() into State - [38]
H46LUUZYhydra-queue-runner: don't try to distribute builds on localhost - [39]
PW4TLMWSSync with latest Nix - [40]
WV4SSAIYBuild against nix-master - [41]
EPWEMRI2Allow determinism checking for entire jobsets - [42]
NWFDDRUGhydra-queue-runner: Limit concurrent database connections - [43]
FITVNQ2SKeep track of the time we spend copying to/from build machines - [44]
MS676RZWRemove s3binarystore (moved to nix in d155d80) - [45]
EBJP3MNABuild against nix-master - [46]
YNO7CQ6Phydra-queue-runner: More accurate memory accounting - [47]
24BMQDZAStart of single-process hydra-queue-runner - [48]
5CNQUQ77Bump Nix - [49]
MHVIT4JYSplit hydra-queue-runner.cc more - [50]
MQNJPMCUFix bad format string - [51]
NAYQT2GThydra-queue-runner: Use cmdBuildDerivation - [52]
5AIYUMTBBasic remote building - [53]
73YR46NJhydra-queue-runner: Write directly to a binary cache - [54]
32KJOERMTurn hydra-notify into a daemon - [55]
V6H6BWMKSync with Nix - [56]
N2NKSKHSRefactor local binary cache code into a subclass - [57]
YXYXJDMBhydra-queue-runner: Write GC roots for outputs paths - [58]
G7KWXSFMDistinguish build step states - [59]
HJOEIMLRRefactor
Change contents
- file deletion: token-server.hh
#pragma once#include <atomic>#include "sync.hh"#include "types.hh"namespace nix {MakeError(NoTokens, Error);/* This class hands out tokens. There are only ‘maxTokens’ tokensavailable. Calling get(N) will return a Token object, representingownership of N tokens. If the requested number of tokens isunavailable, get() will sleep until another thread returns atoken. */class TokenServer{const size_t maxTokens;Sync<size_t> inUse{0};std::condition_variable wakeup;public:TokenServer(size_t maxTokens) : maxTokens(maxTokens) { }class Token{friend TokenServer;TokenServer * ts;size_t tokens;bool acquired = false;Token(TokenServer * ts, size_t tokens, unsigned int timeout): ts(ts), tokens(tokens){if (tokens >= ts->maxTokens)throw NoTokens("requesting more tokens (%d) than exist (%d)", tokens, ts->maxTokens);debug("acquiring %d tokens", tokens);auto inUse(ts->inUse.lock());while (*inUse + tokens > ts->maxTokens)if (timeout) {if (!inUse.wait_for(ts->wakeup, std::chrono::seconds(timeout),[&]() { return *inUse + tokens <= ts->maxTokens; }))return;} elseinUse.wait(ts->wakeup);*inUse += tokens;acquired = true;}public:Token(Token && t) : ts(t.ts), tokens(t.tokens), acquired(t.acquired){t.ts = 0;t.acquired = false;}Token(const Token & l) = delete;~Token(){if (!ts || !acquired) return;{auto inUse(ts->inUse.lock());assert(*inUse >= t);*inUse -= t;tokens -= t;}// FIXME: inefficient. Should wake up waiters that can// proceed now.ts->wakeup.notify_all();}};Token get(size_t tokens = 1, unsigned int timeout = 0){return Token(this, tokens, timeout);}size_t currentUse(){auto inUse_(inUse.lock());return *inUse_;}};}size_t capacity(){return maxTokens;}give_back(tokens);}bool operator ()() { return acquired; }void give_back(size_t t){debug("returning %d tokens", t);if (!t) return;assert(acquired);assert(t <= tokens); - replacement in src/hydra-queue-runner/Makefile.am at line 5
build-result.hh counter.hh token-server.hh state.hh db.hhbuild-result.hh counter.hh state.hh db.hh - edit in src/hydra-queue-runner/build-remote.cc at line 428[4.2468]→[4.523:524](∅→∅),[4.2975]→[4.523:524](∅→∅),[4.8075]→[4.523:524](∅→∅),[4.523]→[4.523:524](∅→∅),[4.524]→[4.8076:8141](∅→∅),[4.8141]→[4.0:264](∅→∅),[4.264]→[4.8244:8306](∅→∅),[4.8244]→[4.8244:8306](∅→∅),[4.8306]→[4.265:457](∅→∅),[4.457]→[4.8374:8435](∅→∅),[4.8374]→[4.8374:8435](∅→∅),[4.8435]→[4.2326:2327](∅→∅),[4.2326]→[4.2326:2327](∅→∅),[4.2327]→[4.8436:8575](∅→∅),[4.8575]→[4.2976:3154](∅→∅)
/* Block until we have the required amount of memoryavailable, which is twice the NAR size (namely theuncompressed and worst-case compressed NAR), plus 150MB for xz compression overhead. (The xz manpage claims~94 MiB, but that's not was I'm seeing.) */auto resStart = std::chrono::steady_clock::now();size_t compressionCost = totalNarSize + 150 * 1024 * 1024;result.tokens = std::make_unique<nix::TokenServer::Token>(memoryTokens.get(totalNarSize + compressionCost));auto resStop = std::chrono::steady_clock::now();auto resMs = std::chrono::duration_cast<std::chrono::milliseconds>(resStop - resStart).count();if (resMs >= 1000)printMsg(lvlError, "warning: had to wait %d ms for %d memory tokens for %s",resMs, totalNarSize, localStore->printStorePath(step->drvPath)); - edit in src/hydra-queue-runner/build-remote.cc at line 434
/* Release the tokens pertaining to NARcompression. After this we only have the uncompressedNAR in memory. */result.tokens->give_back(compressionCost); - edit in src/hydra-queue-runner/builder.cc at line 207[4.712]→[4.2415:2504](∅→∅),[4.1043]→[4.2415:2504](∅→∅),[4.1161]→[4.2415:2504](∅→∅),[4.1230]→[4.2415:2504](∅→∅),[4.1432]→[4.2415:2504](∅→∅)
} catch (NoTokens & e) {result.stepStatus = bsNarSizeLimitExceeded; - edit in src/hydra-queue-runner/builder.cc at line 225
result.tokens = 0; - edit in src/hydra-queue-runner/hydra-queue-runner.cc at line 52
, memoryTokens(config->getIntOption("nar_buffer_size", getMemSize() / 2)) - edit in src/hydra-queue-runner/hydra-queue-runner.cc at line 57
debug("using %d bytes for the NAR buffer", memoryTokens.capacity()); - edit in src/hydra-queue-runner/hydra-queue-runner.cc at line 544
root.attr("memoryTokensInUse", memoryTokens.currentUse()); - edit in src/hydra-queue-runner/state.hh at line 11
#include "token-server.hh" - edit in src/hydra-queue-runner/state.hh at line 67
std::unique_ptr<nix::TokenServer::Token> tokens; - edit in src/hydra-queue-runner/state.hh at line 411
/* Token server to prevent threads from allocating too many bigstrings concurrently while importing NARs from the buildmachines. When a thread imports a NAR of size N, it will firstacquire N memory tokens, causing it to block until that manytokens are available. */nix::TokenServer memoryTokens;