libstore: turn Worker::updateStatistics into a promise
we'll now loop to update displayed statistics, and use this loop to
limit the update rate to 50 times per second. we could have updated
much more frequently before this (once per iteration of `runImpl`),
much faster than would ever be useful in practice. aggressive stats
updates can even impede progress due to terminal or network delays.
Change-Id: Ifba755a2569f73c919b1fbb06a142c0951395d6d
This commit is contained in:
parent
732de75f67
commit
9889c79fe3
|
@ -258,11 +258,13 @@ void Worker::childTerminated(GoalPtr goal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Worker::updateStatistics()
|
kj::Promise<Result<void>> Worker::updateStatistics()
|
||||||
{
|
try {
|
||||||
|
while (true) {
|
||||||
|
statisticsUpdateInhibitor = co_await statisticsUpdateSignal.acquire();
|
||||||
|
|
||||||
// only update progress info while running. this notably excludes updating
|
// only update progress info while running. this notably excludes updating
|
||||||
// progress info while destroying, which causes the progress bar to assert
|
// progress info while destroying, which causes the progress bar to assert
|
||||||
if (running && statisticsOutdated) {
|
|
||||||
actDerivations.progress(
|
actDerivations.progress(
|
||||||
doneBuilds, expectedBuilds + doneBuilds, runningBuilds, failedBuilds
|
doneBuilds, expectedBuilds + doneBuilds, runningBuilds, failedBuilds
|
||||||
);
|
);
|
||||||
|
@ -275,8 +277,11 @@ void Worker::updateStatistics()
|
||||||
act.setExpected(actFileTransfer, expectedDownloadSize + doneDownloadSize);
|
act.setExpected(actFileTransfer, expectedDownloadSize + doneDownloadSize);
|
||||||
act.setExpected(actCopyPath, expectedNarSize + doneNarSize);
|
act.setExpected(actCopyPath, expectedNarSize + doneNarSize);
|
||||||
|
|
||||||
statisticsOutdated = false;
|
// limit to 50fps. that should be more than good enough for anything we do
|
||||||
|
co_await aio.provider->getTimer().afterDelay(20 * kj::MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
} catch (...) {
|
||||||
|
co_return result::failure(std::current_exception());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<GoalPtr> Worker::run(std::function<Targets (GoalFactory &)> req)
|
std::vector<GoalPtr> Worker::run(std::function<Targets (GoalFactory &)> req)
|
||||||
|
@ -287,14 +292,12 @@ std::vector<GoalPtr> Worker::run(std::function<Targets (GoalFactory &)> req)
|
||||||
running = true;
|
running = true;
|
||||||
Finally const _stop([&] { running = false; });
|
Finally const _stop([&] { running = false; });
|
||||||
|
|
||||||
updateStatistics();
|
|
||||||
|
|
||||||
topGoals.clear();
|
topGoals.clear();
|
||||||
for (auto & [goal, _promise] : _topGoals) {
|
for (auto & [goal, _promise] : _topGoals) {
|
||||||
topGoals.insert(goal);
|
topGoals.insert(goal);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto promise = runImpl();
|
auto promise = runImpl().exclusiveJoin(updateStatistics());
|
||||||
|
|
||||||
// TODO GC interface?
|
// TODO GC interface?
|
||||||
if (auto localStore = dynamic_cast<LocalStore *>(&store); localStore && settings.minFree != 0) {
|
if (auto localStore = dynamic_cast<LocalStore *>(&store); localStore && settings.minFree != 0) {
|
||||||
|
|
|
@ -167,16 +167,17 @@ private:
|
||||||
/**
|
/**
|
||||||
* Pass current stats counters to the logger for progress bar updates.
|
* Pass current stats counters to the logger for progress bar updates.
|
||||||
*/
|
*/
|
||||||
void updateStatistics();
|
kj::Promise<Result<void>> updateStatistics();
|
||||||
|
|
||||||
bool statisticsOutdated = true;
|
AsyncSemaphore statisticsUpdateSignal{1};
|
||||||
|
std::optional<AsyncSemaphore::Token> statisticsUpdateInhibitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark statistics as outdated, such that `updateStatistics` will be called.
|
* Mark statistics as outdated, such that `updateStatistics` will be called.
|
||||||
*/
|
*/
|
||||||
void updateStatisticsLater()
|
void updateStatisticsLater()
|
||||||
{
|
{
|
||||||
statisticsOutdated = true;
|
statisticsUpdateInhibitor = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
kj::Promise<Result<void>> runImpl();
|
kj::Promise<Result<void>> runImpl();
|
||||||
|
|
Loading…
Reference in a new issue