irmin-pack.unix: Use asynchronous unlink when cleaning up chunks in Gc.#2221
irmin-pack.unix: Use asynchronous unlink when cleaning up chunks in Gc.#2221metanivek merged 1 commit intomirage:mainfrom
Conversation
|
In case this is not enough, we don't actually need to wait for the unlinks to terminate (we also don't need the files to be deleted in a specific order, so perhaps with |
|
I've run a benchmark to see how this performs (https://github.com/tarides/irmin-tezos-benchmarking/tree/async-unlink/benchmarks/2023-03-async-unlink). Tail latencies (compared to 3.7-mvp): Slightly better. I think we can improve more by doing multiple unlinks at the same time. Currently all old chunks are unlinked sequentially in a Slightly suprising, the disk usage: Maybe Lwt is doing something funky? |
Absolutely, I'll run another benchmark run where the unlinks just happen "fire and forget". Maybe using |
Seems like the disk usage watch script is trying to compute size of When Seems to be related to #2206. |
Codecov Report
📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more @@ Coverage Diff @@
## main #2221 +/- ##
==========================================
- Coverage 68.09% 68.07% -0.02%
==========================================
Files 135 135
Lines 16480 16492 +12
==========================================
+ Hits 11222 11227 +5
- Misses 5258 5265 +7
... and 1 file with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
|
Regarding |
|
Thanks for tackling this! I think the key will be to not bind the promise of Perhaps this can be wrapped up inside of the Io module with something like (or with a custom exn handler so callers can do whatever they like): let unlink_async path =
let log_exn = (* log exn :) *) in
let lwt_unlink = fun () -> Lwt_unix.unlink path in
Lwt.dont_wait lwt_unlink log_exn
end |
|
And the results are in for the unlink-and-forget version:
Seems to work.
That's pretty much the logic we have now. Wrapping it in the
Yes, good point! We are a bit too conservative with |
|
I guess my main thought is that moving it into Once we do that, I expect the tail latency to be around the 200ms or so that you observed in the benchmark that did not unlink files. |
You're right:
The And uses this from |
This introduces `Io.unlink_dont_wait` that unlinks files but doesn't wait for completion and uses it when cleaning up after a GC run. Resolves mirage#2202 and mirage#2091.
…le has been unlinked asynchronously. This fixes flakey test failures introduced by mirage#2221 caused by files still existing that are being unlinked asynchronously. The introduced `check_asyn_unlinked` function takes a timeout argument and checks if the file has been unlinked within the specified timeout period.

First try to tackle #2220.
This adds
Io.unlink_asyncwhich callsLwt_unix.unlink.Lwt maintains a pool of system threads where the unlinks will be called, thus not blocking the main application thread.
I'm not sure if this will provide any real benefits as Gc is still waited on by
Async.await.