Port exa perf and bugfix patches onto NixOS/nix 2.36 - #1
Closed
ethancedwards8 wants to merge 8 commits into
Closed
ethancedwards8 wants to merge 8 commits into
ethancedwards8 wants to merge 8 commits into
Conversation
Expose libcurl's CURLMOPT_MAX_CONCURRENT_STREAMS as a `max-http2-streams` setting (default 100, libcurl's default). Setting it to 1 keeps HTTP/2 framing and header compression but disables multiplexing, which avoids head-of-line blocking when a single paused stream (e.g. a slow store import) throttles every other stream on the same TCP connection. Our CI runners set `max-http2-streams = 1` in nix.conf, so the daemon fails to start without this setting (GIGA-2850, GIGA-3360). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Add AttrCursor::cachedGetStringWithContext(), a cache-only variant of getStringWithContext() that returns std::nullopt on a miss instead of falling through to forceValue(). Use it in `nix eval` for plain flake attribute evaluations (no --apply / --write-to): if the attribute is a string that is already in the eval-cache database and every store path in its context is still valid, print it without evaluating the flake at all. This skips derivationStrict for e.g. `nix eval .#foo.outPath` whenever the flake inputs haven't changed. Temp roots are added for context paths, as the existing cached branch of getStringWithContext() does, and ensureLazyPathsCopied() is still run on the cached context. Re-implementation of exa-labs/nix-src 8948813 against NixOS/nix 2.36 (GIGA-2848, GIGA-3360). Differences from the original: the `Path` string-context variant no longer exists upstream; errors other than `Error` (notably Interrupted) are not swallowed by the fast path. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The libgc default free space divisor is 3, i.e. the heap grows ~33% after each collection. Setting it to 1 makes the heap double instead, roughly halving the number of collections. Measured on a full-nixpkgs `nix-env -qa --out-path`: ~104s -> ~84s wall (-20%) for 15.2 GB -> 19.8 GB peak RSS (+30%). This one change accounts for essentially the whole end-to-end win of the exa perf series (GIGA-2849). Unlike the original fork patch, the value is only applied when the GC_FREE_SPACE_DIVISOR environment variable is unset, matching how GC_INITIAL_HEAP_SIZE is already handled here. libgc reads that variable in GC_INIT(); unconditionally overriding it afterwards left users with no way to opt back out on memory-constrained machines (`GC_FREE_SPACE_DIVISOR=3 nix ...` now restores stock behaviour). Re-implementation of exa-labs/nix-src 319801a against NixOS/nix 2.36 (GIGA-3360). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Both encoders built their result with reserve() + push_back(), paying a capacity check per character. Allocate the exact-length string up front and write through a pointer instead. base16::encode additionally uses a constexpr byte -> two-digit table so each input byte is a single lookup rather than two nibble lookups. These are hot in hash printing (store path computation, narinfo handling, eval-cache keys). Output is byte-for-byte unchanged; the existing unit tests in src/libutil-tests cover both encoders. Re-implementation of exa-labs/nix-src e781363 and 196a532 against NixOS/nix 2.36 (GIGA-2839, GIGA-2840, GIGA-3360). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Callback::operator() and Callback::rethrow() asserted that they were the first invocation. Under load, HttpBinaryCacheStore::getFile could complete its callback twice: once from the FileTransfer completion handler and once from the surrounding catch(...) when enqueueing raced with a failure, taking the daemon down with SIGABRT (NixOS#13484, still open upstream). A callback that has been fulfilled cannot be un-fulfilled, so a second invocation is now a no-op. Since both entry points are noexcept, an exception escaping the wrapped lambda is now routed through ignoreExceptionInDestructor() (logged, not terminating) rather than calling std::terminate. Also split the try/catch in HttpBinaryCacheStore::getFile so a disabled cache reports through the callback before anything is enqueued, narrowing the window in which two paths can race for the same callback. This is deliberately a hardening fix, not a root-cause fix; see GIGA-2851 for the follow-up. Re-implementation of exa-labs/nix-src 8a8eedd against NixOS/nix 2.36 (GIGA-3360). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…kers Two related fixes for daemon workers that outlive their client (NixOS#15691, still open upstream): * MonitorFdHup (poll() variant): also treat POLLERR and POLLNVAL as a hangup. A client socket that errors out rather than closing cleanly is never reported as POLLHUP, so poll() returned immediately forever and the monitor thread spun at 100% CPU while the worker kept going. * nix-daemon: after fork(), the worker inherits the daemon's blocked signal mask but not its signal handler thread, so it could never observe SIGTERM/SIGINT/SIGPIPE. Restore the mask saved at daemon startup and start a fresh handler thread in the worker. The order matters: startSignalHandlerThread() re-saves the current mask, and saving the already-blocked mask would later be reapplied to build children via restoreProcessContext(), leaving signals blocked in builders. Re-implementation of exa-labs/nix-src 56de571 against NixOS/nix 2.36 (GIGA-2838, GIGA-3360). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The per-client thread in LocalStore::collectGarbage that reads temp roots from connected clients only caught Error. Interrupted derives from BaseError, not Error, so an interrupt raised while blocked in readLine() (e.g. the daemon worker being told to shut down mid-GC) escaped the std::thread and took the whole nix-daemon down via std::terminate. Catch it and leave the loop like any other client disconnect. Re-implementation of exa-labs/nix-src aff8949 against NixOS/nix 2.36 (GIGA-3360). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
When autoGC(sync=true) found a GC pass already running it always waited for it to finish. A pass over a large store can take hours, and during that time every store add on the machine (builds, substitutions, `nix copy` into the store) was stalled, even with plenty of free space. Adds are safe to run concurrently with GC via the temp-roots protocol, so only wait when free space is actually below the `min-free` floor; otherwise return immediately and let the add proceed. The `!sync` case is unchanged in effect (it never waited). Re-implementation of exa-labs/nix-src 2b9074b against NixOS/nix 2.36 (GIGA-3360). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Member
Author
|
Superseded by a PR against the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Part 1 of 3 for GIGA-3360: re-implementation (not cherry-pick) of the
exa/patchedperf + bugfix series fromexa-labs/nix-srcagainst upstream 2.36.0 (36a6e9d6d). One commit per patch; each message links the original nix-src commit and the GIGA-2837 sub-issue.max-http2-streamssetting (required — runners set it to 1 and the daemon won't start without it)nix evalfast path: serve cached flake string attrs straight from the eval cache (GIGA-2848)GC_FREE_SPACE_DIVISORenv override, which the original patch clobbered (GIGA-2849)Callbackidempotent instead ofassert-aborting on double invoke;HttpBinaryCacheStore::getFiletry/catch split (Nix daemon crashes with assertion failure when building multiple mlibc cross-compiled packages NixOS/nix#13484, GIGA-2851)MonitorFdHuptreatsPOLLERR|POLLNVALas hangup; forked workers restore signal mask + start a handler thread (Fix MonitorFdHup 100% CPU spin and unresponsive daemon workers NixOS/nix#15691, GIGA-2838)Interruptedin the GC-roots client thread (wasstd::terminate-ing the daemon)autoGC(sync)no longer blocks store adds behind a running pass when abovemin-freeDropped vs nix-src (per GIGA-2837 verdicts / already upstream): checkName LUT (GIGA-2853), printString scan-and-copy (GIGA-2852),
nix runeval-cache fix (upstream now clearsevalCachesbefore exec in run/develop/env/formatter),forward-aws-credentials+ its revert.Adaptations to 2.36:
NixStringContextElem::Pathvariant is gone;getCursortakesAutoCall; the fast path only swallowsError, notInterrupted; Callback usesignoreExceptionInDestructor()rather than a silentcatch(...).Test plan
debugoptimized)nix-util-tests,nix-store-tests,nix-expr-tests,nix-fetchers-tests,nix-flake-testsall passeval,eval-cache,flakes,gc-auto,gc-non-blocking,gc-concurrent,binary-cache,config,hash-*,eval-store(main + ca) passnix config showshowsmax-http2-streams = 100;--option max-http2-streams 1acceptednix eval .#attron a flake: 2nd run logsusing cached string attribute;--raw/--jsonmatch;--applybypasses the fast pathGC_FREE_SPACE_DIVISOR=3 nix eval --expr 1+1worksexa-build.yml(lands in the plumbing PR)nix-perf-benchmarksagainst this base (follow-up)Generated with Devin