You can now set 'evaluator_max_heap_size' to make hydra-eval-jobs restart itself if the Boehm heap exceeds the specified size.
For example, with 'evaluator_max_heap_size = 256000000',
$ hydra-eval-jobs '<nixpkgs/pkgs/top-level/release.nix>' -I nixpkgs=channel:nixos-17.09
has a max RSS of .56 GiB rather than 4.7 GiB.
Unfortunately it doesn't help much for the NixOS jobsets because of the "tested" job which requires a huge amount of memory all by itself.
5MP35ORVVILU3GXYITYXD754QFZCOZ3X45QO54K2GW5UKNHX66SAC
4GTOWRFWCVZJHG6ZQTXI5XMQO3QGHBGAV52IQKEDS6NYW5CI343AC
HP5WJLQUNP7PXGVBYOMWRCZ4QKDECULS2EAFX2FPHRUXV2CMMYCAC
ZVSHXE3KY43J5BBDGERORR2FAVDG4ARANUUSGIYDHUN767SQ4GAQC
FGLKIVYSAUOB3FP33SQCPXP3ZZLSDDV2SS2NEP6L6TQVRYQU4ETQC
4N5APGRGHTKFMEJ7THSJX6TSYYAP3BUZQG73AJBKCQLXOOEHPATQC
KD5237CUR4X3VRUD46H3CVU22NYS7LOPF3WXENWHNSF7GKEIQZ6QC
AEKIREIHNEHL4CQEHRZJGRWMCV2XO6ICZK2OM342IKAJV6MUMDOAC
IMQRX4MPANNOXDP6THT2FA4576CDFY44LGNCS74BHV6DWLOCXQOQC
4LWGZL33NOCTVZXUZZM5P6BRBHDUMEAJPVPNB52PN3UZVC7DMSZAC
L4LBF7UFTG7SVPSZNHINTDQRXEOW7IX4AUASALYHDGMMAWRX6U7QC
I2HYJBMLEXCUGUWZML5LVR2SR6TI3XAS4MSCRYOK6T44M4MYTDCAC
FGUL3HAZDA6JGTAZNCJZIIKALZ4VMVTXYWFNSXWDYR5LXNGCO3RAC
HNGPGVBTFCEYF4YCAUTDGADAU7IXQBAAUNE6RIFUD3HXFGU5QPBAC
STZE4KKRL2AGCPP2FOMBNZHJTRTKJQZSEKALWEV6FK5BII6H7EDAC
VTNP5KDOVQPWGRARMFJJ3MTU7IAZT4NP7ZFY4HJYT3KYJUSAZEZAC
M5BEPXTEW5BTPKV4PIJAVFLWE6CBHZ7FF2UFE5QIOPL2BQE3RDTAC
EBG4P4SYFPBR4LPHN6Q74YLBWFT33TDKF6QAHHQ77EEWP7SZCWOQC
7GKAIP3VYKM4MGGHOGBB3DR2M6B6SENBR5IZQVJYO65AWT4BW7LAC
FUB37KFUYUROEDXICXDZJTQCE6K5GOTRMSWZHIVDRPUYJR2MMO5QC
VTMBJVIS6JEZVGC3QHM45LVJDSEOSSTOXSYEBDZE3BK3SHOM2TUQC
3PNG7NIBQQURUUPRVQXYL342OT7JUUYOMY2JJNP6YDX7SYJDZMYAC
WMWBCZPRDLX57HUCWCOVIYOYGEQGOVL3PQW67F327RD77FD5D2JAC
bool lte(const std::string & s1, const std::string & s2)
{
size_t p1 = 0, p2 = 0;
while (true) {
if (p1 == s1.size()) return p2 == s2.size();
if (p2 == s2.size()) return true;
auto d1 = s1.find('.', p1);
auto d2 = s2.find('.', p2);
auto c = s1.compare(p1, d1 - p1, s2, p2, d2 - p2);
if (c < 0) return true;
if (c > 0) return false;
p1 = d1 == std::string::npos ? s1.size() : d1 + 1;
p2 = d2 == std::string::npos ? s2.size() : d2 + 1;
}
}
for (auto & i : *v.attrs)
findJobs(state, top, autoArgs, *i.value,
(attrPath.empty() ? "" : attrPath + ".") + (string) i.name);
for (auto & i : v.attrs->lexicographicOrder()) {
std::string name(i->name);
/* Skip jobs with dots in the name. */
if (name.find('.') != std::string::npos) {
printError("skipping job with illegal name '%s'", name);
continue;
}
findJobs(state, top, autoArgs, *i->value,
(attrPath.empty() ? "" : attrPath + ".") + name);
}
assert(lte("abc", "def"));
assert(lte("abc", "def.foo"));
assert(!lte("def", "abc"));
assert(lte("nixpkgs.hello", "nixpkgs"));
assert(lte("nixpkgs.hello", "nixpkgs.hellooo"));
assert(lte("gitAndTools.git-annex.x86_64-darwin", "gitAndTools.git-annex.x86_64-linux"));
assert(lte("gitAndTools.git-annex.x86_64-linux", "gitAndTools.git-annex-remote-b2.aarch64-linux"));
state.printStats();
if (gcRootsDir == "") printMsg(lvlError, "warning: `--gc-roots-dir' not specified");
EvalState state(myArgs.searchPath, openStore());
Bindings & autoArgs = *myArgs.getAutoArgs(state);
Value v;
state.evalFile(lookupFileArg(state, releaseExpr), v);
comma = lastAttrPath != "";
try {
findJobs(state, json, autoArgs, v, "");
lastAttrPath = "";
} catch (BailOut &) { }
writeFull(pipe.writeSide.get(), lastAttrPath);
exit(0);
}, options);
pipe.writeSide = -1;
int status;
while (true) {
checkInterrupt();
if (waitpid(pid, &status, 0) == pid) break;
if (errno != EINTR) continue;
}
if (status != 0)
throw Exit(WIFEXITED(status) ? WEXITSTATUS(status) : 99);
lastAttrPath = drainFD(pipe.readSide.get());
} while (lastAttrPath != "");