Speed up cache size command (#17015)

## Summary

`uv cache size` can be quite slow. Here i use
https://github.com/sharkdp/diskus to walk the cache directory with in
multiple threads.

Add cli option to set the number of threads and default to `
std:🧵:available_parallelism()` or 1.

## Test Plan

Added cli statement with info log test.

I believe this is a fair test, where i set cache dir to a large
directory.

```bash
matthew@matthew-main ~/develop/personal/uv                                                                                                                                                                                                                 [14:17:50]                                                                                                                                                                                                                                       [±cache-size-speed-up ✓▴]
> $ uv cache size --preview-features cache-size -H --cache-dir ~/develop/                                                                                                                                                                   [±cache-size-speed-up ✓▴]
75.7GiB

matthew@matthew-main ~/develop/personal/uv                                                                                                                                                                                                                 [14:18:24]
> $ hyperfine 'uv cache size --preview-features cache-size -H --cache-dir ~/develop/' 'target/debug/uv cache size --preview-features cache-size -H --cache-dir ~/develop/'                                                                  [±cache-size-speed-up ✓▴]
Benchmark 1: uv cache size --preview-features cache-size -H --cache-dir ~/develop/
  Time (mean ± σ):      1.059 s ±  0.014 s    [User: 0.171 s, System: 0.884 s]
  Range (min … max):    1.048 s …  1.097 s    10 runs

Benchmark 2: target/debug/uv cache size --preview-features cache-size -H --cache-dir ~/develop/
  Time (mean ± σ):     413.8 ms ±  17.1 ms    [User: 5789.2 ms, System: 1682.0 ms]
  Range (min … max):   386.3 ms … 441.6 ms    10 runs

Summary
  target/debug/uv cache size --preview-features cache-size -H --cache-dir ~/develop/ ran
    2.56 ± 0.11 times faster than uv cache size --preview-features cache-size -H --cache-dir ~/develop/  
```
This commit is contained in:
Matthew Mckee 2025-12-11 17:11:01 +00:00 committed by GitHub
parent 59d73fdddf
commit 6de869cc88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 30 additions and 14 deletions

28
Cargo.lock generated
View File

@ -1038,6 +1038,15 @@ dependencies = [
"itertools 0.10.5",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
@ -1255,6 +1264,16 @@ dependencies = [
"windows-sys 0.61.0",
]
[[package]]
name = "diskus"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec07379c016f78e7ddcd953663b9ed17928ff384928d34d824ed7e463bd3d908"
dependencies = [
"crossbeam-channel",
"rayon",
]
[[package]]
name = "dispatch2"
version = "0.3.0"
@ -3443,9 +3462,9 @@ dependencies = [
[[package]]
name = "rayon"
version = "1.10.0"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [
"either",
"rayon-core",
@ -3453,9 +3472,9 @@ dependencies = [
[[package]]
name = "rayon-core"
version = "1.12.1"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
@ -5402,6 +5421,7 @@ dependencies = [
"clap",
"console 0.16.1",
"ctrlc",
"diskus",
"dotenvy",
"dunce",
"embed-manifest",

View File

@ -103,6 +103,7 @@ ctrlc = { version = "3.4.5" }
cyclonedx-bom = { version = "0.8.0" }
dashmap = { version = "6.1.0" }
data-encoding = { version = "2.6.0" }
diskus = { version = "0.9.0", default-features = false }
dotenvy = { version = "0.15.7" }
dunce = { version = "1.0.5" }
either = { version = "1.13.0" }

View File

@ -75,6 +75,7 @@ base64 = { workspace = true }
clap = { workspace = true, features = ["derive", "string", "wrap_help"] }
console = { workspace = true }
ctrlc = { workspace = true }
diskus = { workspace = true }
dotenvy = { workspace = true }
dunce = { workspace = true }
flate2 = { workspace = true, default-features = false }

View File

@ -1,6 +1,7 @@
use std::fmt::Write;
use anyhow::Result;
use diskus::DiskUsage;
use crate::commands::{ExitStatus, human_readable_bytes};
use crate::printer::Printer;
@ -31,16 +32,9 @@ pub(crate) fn cache_size(
return Ok(ExitStatus::Success);
}
// Walk the entire cache root
let total_bytes: u64 = walkdir::WalkDir::new(cache.root())
.follow_links(false)
.into_iter()
.filter_map(Result::ok)
.filter_map(|entry| match entry.metadata() {
Ok(metadata) if metadata.is_file() => Some(metadata.len()),
_ => None,
})
.sum();
let disk_usage = DiskUsage::new(vec![cache.root().to_path_buf()]);
let total_bytes = disk_usage.count_ignoring_errors();
if human_readable {
let (bytes, unit) = human_readable_bytes(total_bytes);