Visitar URL original
RestoreSink: start writeback while restoring large files by czawistowski-nvidia · Pull Request #765 · DeterminateSystems/nix-src · GitHub
Skip to content

RestoreSink: start writeback while restoring large files - #765

Open
czawistowski-nvidia wants to merge 1 commit into
DeterminateSystems:mainfrom
czawistowski-nvidia:upstream/restore-writeback
Open

czawistowski-nvidia wants to merge 1 commit into
DeterminateSystems:mainfrom
czawistowski-nvidia:upstream/restore-writeback

Conversation

@czawistowski-nvidia

Copy link
Copy Markdown

Motivation

With fsync-store-paths = true, RestoreSink starts writeback of a restored regular file only when the file is closed (AutoCloseFD::startFsync(), i.e. sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WRITE)). The fsync before registration then waits for the whole file to reach the disk, and every path that refers to it waits too. While a large file streams in from a substituter the disk sits idle, then has to write all of it at the end: for a 731 MiB file streamed at 230 MB/s the final fsync took 1.21 s, versus 0.01 s with writeback started as the file is written.

Change

  • AutoCloseFD::startFsync() takes an optional byte range (default: the whole file, as before).
  • When fsync-store-paths is on, RestoreRegularFile starts writeback of each 32 MiB as it is written, and of the remaining tail at close.
  • The fsync before registration is unchanged, so durability is unchanged. sync_file_range() stays Linux-only and advisory, and its errors are still ignored. With fsync-store-paths = false nothing changes.

Testing

  • New functional test restore-large-file.sh: substitutes a 100 MiB file with fsync-store-paths = true and checks its registration and contents. (That writeback now starts per chunk shows up under strace -e sync_file_range as ranged calls; there's no cheap way to assert that in a test.)
  • On this branch: restore-large-file, binary-cache, binary-cache-compression, nars, nar-access, substitute-with-invalid-ca, multiple-outputs-substitute-failure, nix-util-tests and nix-util-tests-without-new-syscalls pass.
  • Installing two of our own (non-public) closures from an HTTP binary cache into a fresh store on an ext4 cloud VM, fsync-store-paths = true, paired interleaved runs (n = 34 each): install time −14% ± 5.3% (95% CI) on a closure dominated by a few multi-hundred-MiB files, −6.9% on another. To reproduce without our closures: substitute any path containing a file of several hundred MiB and time the final fsync (strace -T -e fsync,sync_file_range).

With fsync-store-paths, RestoreSink started writeback of a regular file
(sync_file_range(SYNC_FILE_RANGE_WRITE)) only when the file was closed, so
the fsync before registering the path waited for the whole file to reach
the disk. Start writeback of each 32 MiB as it is written instead, so the
disk writes while the rest of the NAR is still being downloaded and
unpacked. The fsync before registration is unchanged; sync_file_range is
only a hint and its errors are still ignored.
@coderabbitai

coderabbitai Bot commented Nov 6, 2026

Copy link
Copy Markdown

Warning

Review limit reached

  • Run on-demand review

This review includes 5 billable files and costs up to $1.25.

Or wait 59 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e5e26690-a11e-4631-a7f1-f9eda2326e4a
Commits

Reviewing files that changed from the base of the PR and between 7fa39d9 and 7a809dc.

Files selected for processing: 5

  • src/libutil/file-descriptor.cc
  • src/libutil/fs-sink.cc
  • src/libutil/include/nix/util/file-descriptor.hh
  • tests/functional/meson.build
  • tests/functional/restore-large-file.sh
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant