refactor: Introduce CacheKey trait (#3323)

This PR introduces a new `CacheKey` trait for types that can be used as a cache key.

I'm not entirely sure if this is worth the "overhead", but I was surprised to find `HashableHashSet` and got scared when I looked at the time complexity of the `hash` function. These implementations must be extremely slow in hashed collections.

I then searched for usages and quickly realized that only the cache uses these `Hash` implementations, where performance is less sensitive.

This PR introduces a new `CacheKey` trait to communicate the difference between a hash and computing a key for the cache. The new trait can be implemented for types that don't implement `Hash` for performance reasons, and we can define additional constraints on the implementation:  For example, we'll want to enforce portability when we add remote caching support. Using a different trait further allows us not to implement it for types without stable identities (e.g. pointers) or use other implementations than the standard hash function.
This commit is contained in:
Micha Reiser 2023-03-03 19:29:49 +01:00 committed by GitHub
parent d1288dc2b1
commit cdbe2ee496
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 842 additions and 331 deletions

View file

@ -1,6 +1,5 @@
use std::collections::hash_map::DefaultHasher;
use std::fs;
use std::hash::{Hash, Hasher};
use std::hash::Hasher;
use std::io::Write;
use std::path::Path;
@ -10,6 +9,7 @@ use log::error;
use path_absolutize::Absolutize;
use ruff::message::Message;
use ruff::settings::{flags, AllSettings, Settings};
use ruff_cache::{CacheKey, CacheKeyHasher};
use serde::{Deserialize, Serialize};
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
@ -37,18 +37,18 @@ fn cache_key<P: AsRef<Path>>(
settings: &Settings,
autofix: flags::Autofix,
) -> u64 {
let mut hasher = DefaultHasher::new();
CARGO_PKG_VERSION.hash(&mut hasher);
path.as_ref().absolutize().unwrap().hash(&mut hasher);
let mut hasher = CacheKeyHasher::new();
CARGO_PKG_VERSION.cache_key(&mut hasher);
path.as_ref().absolutize().unwrap().cache_key(&mut hasher);
package
.as_ref()
.map(|path| path.as_ref().absolutize().unwrap())
.hash(&mut hasher);
FileTime::from_last_modification_time(metadata).hash(&mut hasher);
.cache_key(&mut hasher);
FileTime::from_last_modification_time(metadata).cache_key(&mut hasher);
#[cfg(unix)]
metadata.permissions().mode().hash(&mut hasher);
settings.hash(&mut hasher);
autofix.hash(&mut hasher);
metadata.permissions().mode().cache_key(&mut hasher);
settings.cache_key(&mut hasher);
autofix.cache_key(&mut hasher);
hasher.finish()
}