Repository navigation
perf(run): do file-backend I/O on the main thread (LAB-12103) - #45
Merged
Merged
Conversation
Enable cachekit-rs's `unsync` feature. Its file backend then runs each read and write inline instead of on tokio's blocking pool, so a hit no longer starts a thread just to read one entry. ck already drives the backend from one current-thread runtime, so no source change is needed. The fake saas backend's impl becomes `async_trait(?Send)` to match the trait under `unsync`. The helper-thread test now expects exactly the signal thread on a file-backend miss. A new test proves output past the capture cap still streams while the command runs: a miss does no backend I/O until the command exits.
Code Review Completed! 🔥The code review was successfully completed based on your current configurations. Kody Guide: Usage and ConfigurationInteracting with Kody
Providing Context (Files & MCPs)Add these hints in your PR description (or a comment) to unlock deeper checks:
Current Kody ConfigurationReview OptionsThe following review options are enabled or disabled:
|
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.
A file-backend
ck runhit no longer starts a thread. This PR enables cachekit-rs'sunsyncfeature, so the file backend reads and writes inline on ck's main thread instead of handing each operation to tokio's blocking pool. Before, a one-shot process had no pooled thread to reuse, so every hit paid oneclone3to read one entry. Onubuntu-latestthe hit median falls from 1,082 µs to 946 µs (−12.6%), and theck --versionfloor stays put.Change
Cargo.toml: addunsyncto thecachekit-rsfeatures.Cargo.lockis unchanged: features are not recorded there, andunsyncpulls in no crate.tests/saas.rs: the fake backend's impl becomes#[async_trait(?Send)], which matches theBackendtrait underunsync.tests/run.rs:helper_threads_block_the_handled_signalsnow expects exactly one helper thread on a file-backend miss, the signal thread, and still checks that it blocks HUP, INT, QUIT and TERM. It used to expect at least two (the signal thread and a blocking-pool thread).tests/run.rs: new testoutput_past_20_mib_is_streamed_while_the_command_runs. The command writes 21 MiB, sleeps 3 s, then touches a file. The test reads all 21 MiB and asserts the file does not exist yet, so the output past the cap reached the caller while the command was still running. A mutantcollectthat holds output until EOF fails it.src/store.rs(why a runtime still exists),src/child.rs(which threads ck starts) andtests/bench.rs(a hit does not list the cache directory).ck's
src/needs no code change: it already drives the backend from one current-thread runtime and never sends a backend future or error across threads.Miss path: nothing new can stall the command
While the command runs, ck does no backend I/O: main reads the pipe and holds output up to the 20 MiB cap, then streams. Only the reads before the run and the write-back after it move onto main. Before, main already blocked on each of those operations (
block_onawaited the blocking task), so they take the same time as before. That includes the first write's sweep for orphaned temp files, which lists the cache directory. The new streaming test pins this down.Measurements (GitHub-hosted, interleaved, A/A floor)
Three arms, each run from one directory under file names of equal length:
A1is base (84aa440),A2is a byte-identical copy of base, andBis this branch. Every round runs all three in shuffled order. There are 200 warm-up rounds, then 3,000 timed rounds per arm for a hit (ck run --ttl 1d -- trueon a warm entry) and 1,000 forck --version. The differences are per-round paired medians with bootstrap 95% CIs. The run used a throwaway probe branch, since deleted: actions run 41196317736.ubuntu-latest, AMD EPYC 7763 (4 vCPU), rustc 1.99.1
--versionAbove the process-start floor, a hit went from about 261 µs to about 126 µs.
macos-latest, Apple M1 (Virtual, 3 CPU), rustc 1.99.1
--versionOn macOS,
--versionalso moved (−37 µs, with a CI that excludes zero) although its code path is unchanged. That is probably binary layout, so roughly a third of the macOS hit gain may be layout rather than the removed thread.strace on a hit (ubuntu-latest, same run): base makes one
clone3per hit, and this branch makes none.Probe harness (
probe/hit.py, not part of this PR)Scope and risk
unsyncis crate-wide. The backend traits become?Send,BackendErrorlosesSend/Sync, and the high-level client swapsArcforRc. ck usesBackend,FileBackend,CachekitIOandEncryptionLayerdirectly, never the client, and it compiles unchanged.unsynctogether withfile. This repo's file-backend tests now exercise that combination: lib 22, run 46, saas 17, readme 1.?Sendbuild gives the same result as base: both binaries print the same 401 message against the live API with a bogus key and then run uncached.Store, so each one gets the same change. The saas path is deliberately unchanged.Checks (local, as CI runs them)
cargo fmt --all -- --check: passcargo clippy --locked --all-targets -- -D warnings: passcargo test --locked: lib 22, readme 1, run 46, saas 17 passed; bench 1 ignored; 0 failedcargo test --locked --release --test bench -- --ignored: passcargo +1.91 check --locked --all-targets(MSRV): passcargo deny check: advisories, bans, licenses, sources okNo docs change: user-visible behaviour is unchanged apart from speed. The README makes no latency or threading claim, and the changelog entry comes from the
perf:commit.Closes LAB-12103