hydra-queue-runner: More accurate memory accounting
We now take into account the memory necessary for compressing the NAR being exported to the binary cache, plus xz compression overhead. Also, we now release the memory tokens for the NAR accessor *after* releasing the NAR accessor. Previously the memory for the NAR accessor might still be in use while another thread does an allocation, causing the maximum to be exceeded temporarily. Also, use notify_all instead of notify_one to wake up memory token waiters. This is not very nice, but not every waiter is requesting the same number of tokens, so some might be able to proceed.
This commit is contained in:
@@ -40,6 +40,7 @@ public:
|
||||
{
|
||||
if (tokens >= ts->maxTokens)
|
||||
throw NoTokens(format("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) {
|
||||
@@ -54,21 +55,38 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
Token(Token && t) : ts(t.ts) { t.ts = 0; }
|
||||
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 >= tokens);
|
||||
*inUse -= tokens;
|
||||
}
|
||||
ts->wakeup.notify_one();
|
||||
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);
|
||||
{
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user