Merge pull request #6913 from edolstra/lazy-trees-cherrypicks

lazy-trees cherrypicks
This commit is contained in:
Eelco Dolstra 2022-08-17 12:20:19 +02:00 committed by GitHub
commit 84cc7ad77c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 39 additions and 37 deletions

View file

@ -616,6 +616,8 @@ InstallableFlake::InstallableFlake(
std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableFlake::toDerivation() std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableFlake::toDerivation()
{ {
Activity act(*logger, lvlTalkative, actUnknown, fmt("evaluating derivation '%s'", what()));
auto attr = getCursor(*state); auto attr = getCursor(*state);
auto attrPath = attr->getAttrPathStr(); auto attrPath = attr->getAttrPathStr();

View file

@ -8,6 +8,7 @@
#include <map> #include <map>
#include <thread> #include <thread>
#include <iostream> #include <iostream>
#include <chrono>
namespace nix { namespace nix {
@ -48,6 +49,7 @@ private:
bool visible = true; bool visible = true;
ActivityId parent; ActivityId parent;
std::optional<std::string> name; std::optional<std::string> name;
std::chrono::time_point<std::chrono::steady_clock> startTime;
}; };
struct ActivitiesByType struct ActivitiesByType
@ -91,10 +93,11 @@ public:
state_.lock()->active = isTTY; state_.lock()->active = isTTY;
updateThread = std::thread([&]() { updateThread = std::thread([&]() {
auto state(state_.lock()); auto state(state_.lock());
auto nextWakeup = std::chrono::milliseconds::max();
while (state->active) { while (state->active) {
if (!state->haveUpdate) if (!state->haveUpdate)
state.wait(updateCV); state.wait_for(updateCV, nextWakeup);
draw(*state); nextWakeup = draw(*state);
state.wait_for(quitCV, std::chrono::milliseconds(50)); state.wait_for(quitCV, std::chrono::milliseconds(50));
} }
}); });
@ -118,7 +121,8 @@ public:
updateThread.join(); updateThread.join();
} }
bool isVerbose() override { bool isVerbose() override
{
return printBuildLogs; return printBuildLogs;
} }
@ -159,11 +163,13 @@ public:
if (lvl <= verbosity && !s.empty() && type != actBuildWaiting) if (lvl <= verbosity && !s.empty() && type != actBuildWaiting)
log(*state, lvl, s + "..."); log(*state, lvl, s + "...");
state->activities.emplace_back(ActInfo()); state->activities.emplace_back(ActInfo {
.s = s,
.type = type,
.parent = parent,
.startTime = std::chrono::steady_clock::now()
});
auto i = std::prev(state->activities.end()); auto i = std::prev(state->activities.end());
i->s = s;
i->type = type;
i->parent = parent;
state->its.emplace(act, i); state->its.emplace(act, i);
state->activitiesByType[type].its.emplace(act, i); state->activitiesByType[type].its.emplace(act, i);
@ -327,10 +333,12 @@ public:
updateCV.notify_one(); updateCV.notify_one();
} }
void draw(State & state) std::chrono::milliseconds draw(State & state)
{ {
auto nextWakeup = std::chrono::milliseconds::max();
state.haveUpdate = false; state.haveUpdate = false;
if (!state.active) return; if (!state.active) return nextWakeup;
std::string line; std::string line;
@ -341,12 +349,25 @@ public:
line += "]"; line += "]";
} }
auto now = std::chrono::steady_clock::now();
if (!state.activities.empty()) { if (!state.activities.empty()) {
if (!status.empty()) line += " "; if (!status.empty()) line += " ";
auto i = state.activities.rbegin(); auto i = state.activities.rbegin();
while (i != state.activities.rend() && (!i->visible || (i->s.empty() && i->lastLine.empty()))) while (i != state.activities.rend()) {
if (i->visible && (!i->s.empty() || !i->lastLine.empty())) {
/* Don't show activities until some time has
passed, to avoid displaying very short
activities. */
auto delay = std::chrono::milliseconds(10);
if (i->startTime + delay < now)
break;
else
nextWakeup = std::min(nextWakeup, std::chrono::duration_cast<std::chrono::milliseconds>(delay - (now - i->startTime)));
}
++i; ++i;
}
if (i != state.activities.rend()) { if (i != state.activities.rend()) {
line += i->s; line += i->s;
@ -366,6 +387,8 @@ public:
if (width <= 0) width = std::numeric_limits<decltype(width)>::max(); if (width <= 0) width = std::numeric_limits<decltype(width)>::max();
writeToStderr("\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K"); writeToStderr("\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K");
return nextWakeup;
} }
std::string getStatus(State & state) std::string getStatus(State & state)

View file

@ -580,7 +580,6 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
try { try {
conn->to.written = 0; conn->to.written = 0;
conn->to.warn = true;
connections->incCapacity(); connections->incCapacity();
{ {
Finally cleanup([&]() { connections->decCapacity(); }); Finally cleanup([&]() { connections->decCapacity(); });
@ -591,7 +590,6 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
dumpString(contents, conn->to); dumpString(contents, conn->to);
} }
} }
conn->to.warn = false;
conn.processStderr(); conn.processStderr();
} catch (SysError & e) { } catch (SysError & e) {
/* Daemon closed while we were sending the path. Probably OOM /* Daemon closed while we were sending the path. Probably OOM

View file

@ -48,24 +48,9 @@ FdSink::~FdSink()
} }
size_t threshold = 256 * 1024 * 1024;
static void warnLargeDump()
{
warn("dumping very large path (> 256 MiB); this may run out of memory");
}
void FdSink::write(std::string_view data) void FdSink::write(std::string_view data)
{ {
written += data.size(); written += data.size();
static bool warned = false;
if (warn && !warned) {
if (written > threshold) {
warnLargeDump();
warned = true;
}
}
try { try {
writeFull(fd, data); writeFull(fd, data);
} catch (SysError & e) { } catch (SysError & e) {
@ -448,11 +433,6 @@ Error readError(Source & source)
void StringSink::operator () (std::string_view data) void StringSink::operator () (std::string_view data)
{ {
static bool warned = false;
if (!warned && s.size() > threshold) {
warnLargeDump();
warned = true;
}
s.append(data); s.append(data);
} }

View file

@ -97,19 +97,17 @@ protected:
struct FdSink : BufferedSink struct FdSink : BufferedSink
{ {
int fd; int fd;
bool warn = false;
size_t written = 0; size_t written = 0;
FdSink() : fd(-1) { } FdSink() : fd(-1) { }
FdSink(int fd) : fd(fd) { } FdSink(int fd) : fd(fd) { }
FdSink(FdSink&&) = default; FdSink(FdSink&&) = default;
FdSink& operator=(FdSink && s) FdSink & operator=(FdSink && s)
{ {
flush(); flush();
fd = s.fd; fd = s.fd;
s.fd = -1; s.fd = -1;
warn = s.warn;
written = s.written; written = s.written;
return *this; return *this;
} }

View file

@ -212,7 +212,8 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
ANSI_BOLD "Last modified:" ANSI_NORMAL " %s", ANSI_BOLD "Last modified:" ANSI_NORMAL " %s",
std::put_time(std::localtime(&*lastModified), "%F %T")); std::put_time(std::localtime(&*lastModified), "%F %T"));
logger->cout(ANSI_BOLD "Inputs:" ANSI_NORMAL); if (!lockedFlake.lockFile.root->inputs.empty())
logger->cout(ANSI_BOLD "Inputs:" ANSI_NORMAL);
std::unordered_set<std::shared_ptr<Node>> visited; std::unordered_set<std::shared_ptr<Node>> visited;

View file

@ -193,7 +193,7 @@ fi
onError() { onError() {
set +x set +x
echo "$0: test failed at:" >&2 echo "$0: test failed at:" >&2
for ((i = 1; i < 16; i++)); do for ((i = 1; i < ${#BASH_SOURCE[@]}; i++)); do
if [[ -z ${BASH_SOURCE[i]} ]]; then break; fi if [[ -z ${BASH_SOURCE[i]} ]]; then break; fi
echo " ${FUNCNAME[i]} in ${BASH_SOURCE[i]}:${BASH_LINENO[i-1]}" >&2 echo " ${FUNCNAME[i]} in ${BASH_SOURCE[i]}:${BASH_LINENO[i-1]}" >&2
done done