blob: f879b07eb41f3bd111550e7dbc879dd1ae471f50 [file] [log] [blame]
//! Benchmarks for the global cache tracker.
use cargo::core::global_cache_tracker::{self, DeferredGlobalLastUse, GlobalCacheTracker};
use cargo::util::cache_lock::CacheLockMode;
use cargo::util::interning::InternedString;
use cargo::util::GlobalContext;
use criterion::{criterion_group, criterion_main, Criterion};
use std::fs;
use std::path::{Path, PathBuf};
// Samples of real-world data.
const GLOBAL_CACHE_SAMPLE: &str = "global-cache-tracker/global-cache-sample";
const GLOBAL_CACHE_RANDOM: &str = "global-cache-tracker/random-sample";
/// A scratch directory where the benchmark can place some files.
fn root() -> PathBuf {
let mut p = PathBuf::from(env!("CARGO_TARGET_TMPDIR"));
p.push("bench_global_cache_tracker");
p
}
fn cargo_home() -> PathBuf {
let mut p = root();
p.push("chome");
p
}
fn initialize_context() -> GlobalContext {
// Set up config.
let shell = cargo::core::Shell::new();
let homedir = cargo_home();
if !homedir.exists() {
fs::create_dir_all(&homedir).unwrap();
}
let cwd = homedir.clone();
let mut gctx = GlobalContext::new(shell, cwd, homedir);
gctx.nightly_features_allowed = true;
gctx.set_search_stop_path(root());
gctx.configure(
0,
false,
None,
false,
false,
false,
&None,
&["gc".to_string()],
&[],
)
.unwrap();
// Set up database sample.
let db_path = GlobalCacheTracker::db_path(&gctx).into_path_unlocked();
if db_path.exists() {
fs::remove_file(&db_path).unwrap();
}
let sample = Path::new(env!("CARGO_MANIFEST_DIR")).join(GLOBAL_CACHE_SAMPLE);
fs::copy(sample, &db_path).unwrap();
gctx
}
/// Benchmarks how long it takes to initialize `GlobalCacheTracker` with an already
/// existing full database.
fn global_tracker_init(c: &mut Criterion) {
let gctx = initialize_context();
let _lock = gctx
.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)
.unwrap();
c.bench_function("global_tracker_init", |b| {
b.iter(|| {
GlobalCacheTracker::new(&gctx).unwrap();
})
});
}
/// Benchmarks how long it takes to save a `GlobalCacheTracker` when there are zero
/// updates.
fn global_tracker_empty_save(c: &mut Criterion) {
let gctx = initialize_context();
let _lock = gctx
.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)
.unwrap();
let mut deferred = DeferredGlobalLastUse::new();
let mut tracker = GlobalCacheTracker::new(&gctx).unwrap();
c.bench_function("global_tracker_empty_save", |b| {
b.iter(|| {
deferred.save(&mut tracker).unwrap();
})
});
}
fn load_random_sample() -> Vec<(InternedString, InternedString, u64)> {
let path = Path::new(env!("CARGO_MANIFEST_DIR")).join(GLOBAL_CACHE_RANDOM);
fs::read_to_string(path)
.unwrap()
.lines()
.map(|s| {
let mut s = s.split(',');
(
s.next().unwrap().into(),
s.next().unwrap().into(),
s.next().unwrap().parse().unwrap(),
)
})
.collect()
}
/// Tests performance of updating the last-use timestamps in an already
/// populated database.
///
/// This runs for different sizes of number of crates to update (selecting
/// from the random sample stored on disk).
fn global_tracker_update(c: &mut Criterion) {
let gctx = initialize_context();
let _lock = gctx
.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)
.unwrap();
let sample = Path::new(env!("CARGO_MANIFEST_DIR")).join(GLOBAL_CACHE_SAMPLE);
let db_path = GlobalCacheTracker::db_path(&gctx).into_path_unlocked();
let random_sample = load_random_sample();
let mut group = c.benchmark_group("global_tracker_update");
for size in [1, 10, 100, 500] {
if db_path.exists() {
fs::remove_file(&db_path).unwrap();
}
fs::copy(&sample, &db_path).unwrap();
let mut deferred = DeferredGlobalLastUse::new();
let mut tracker = GlobalCacheTracker::new(&gctx).unwrap();
group.bench_with_input(size.to_string(), &size, |b, &size| {
b.iter(|| {
for (encoded_registry_name, name, size) in &random_sample[..size] {
deferred.mark_registry_crate_used(global_cache_tracker::RegistryCrate {
encoded_registry_name: *encoded_registry_name,
crate_filename: format!("{}.crate", name).into(),
size: *size,
});
deferred.mark_registry_src_used(global_cache_tracker::RegistrySrc {
encoded_registry_name: *encoded_registry_name,
package_dir: *name,
size: Some(*size),
});
}
deferred.save(&mut tracker).unwrap();
})
});
}
}
criterion_group!(
benches,
global_tracker_init,
global_tracker_empty_save,
global_tracker_update
);
criterion_main!(benches);