diff --git a/mercury/src/internal/pack/cache.rs b/mercury/src/internal/pack/cache.rs index 244a12f31..7a1a2e727 100644 --- a/mercury/src/internal/pack/cache.rs +++ b/mercury/src/internal/pack/cache.rs @@ -1,6 +1,7 @@ use std::path::Path; use std::path::PathBuf; use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Once; use std::sync::{Arc, Mutex}; use std::thread::sleep; use std::{fs, io}; @@ -42,6 +43,7 @@ pub struct Caches { lru_cache: Mutex>>, mem_size: Option, tmp_path: PathBuf, + path_prefixes: [Once; 256], pool: Arc, complete_signal: Arc, } @@ -77,24 +79,24 @@ impl Caches { self.complete_signal.clone(), Some(self.pool.clone()), ); - x.set_store_path(Caches::generate_temp_path(&self.tmp_path, hash)); + x.set_store_path(self.generate_temp_path(&self.tmp_path, hash)); let _ = map.insert(hash, x); // handle the error Ok(obj) } /// generate the temp file path, hex string of the hash - fn generate_temp_path(tmp_path: &Path, hash: SHA1) -> PathBuf { + fn generate_temp_path(&self, tmp_path: &Path, hash: SHA1) -> PathBuf { let mut path = tmp_path.to_path_buf(); path.push(&hash.to_string()[..2]); // use first 2 chars as the directory - if !path.exists() { + self.path_prefixes[hash.as_ref()[0] as usize].call_once(|| { fs::create_dir(&path).unwrap(); - } + }); path.push(hash.to_string()); path } fn read_from_temp(&self, hash: SHA1) -> io::Result { - let path = Self::generate_temp_path(&self.tmp_path, hash); + let path = self.generate_temp_path(&self.tmp_path, hash); let obj = CacheObject::f_load(&path)?; // Deserializing will also create an object but without Construction outside and `::new()` // So if you want to do sth. while Constructing, impl Deserialize trait yourself @@ -140,6 +142,7 @@ impl _Cache for Caches { lru_cache: Mutex::new(LruCache::new(mem_size.unwrap_or(usize::MAX))), mem_size, tmp_path, + path_prefixes: [const { Once::new() }; 256], pool: Arc::new(ThreadPool::new(thread_num)), complete_signal: Arc::new(AtomicBool::new(false)), } @@ -159,9 +162,7 @@ impl _Cache for Caches { self.complete_signal.clone(), Some(self.pool.clone()), ); - if self.mem_size.is_some() { - a_obj.set_store_path(Caches::generate_temp_path(&self.tmp_path, hash)); - } + a_obj.set_store_path(self.generate_temp_path(&self.tmp_path, hash)); let _ = map.insert(hash, a_obj); } //order maters as for reading in 'get_by_offset()'