performance improvements

This commit is contained in:
sreedevk
2025-07-12 00:24:25 +00:00
parent b4bf5d4fb3
commit f9e86f8522
8 changed files with 103 additions and 274 deletions

View File

@@ -1,107 +1,103 @@
use anyhow::Result;
use dashmap::DashMap;
use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle, ProgressFinish};
use indicatif::{ParallelProgressIterator, ProgressBar, ProgressFinish, ProgressStyle};
use rayon::prelude::{IntoParallelIterator, ParallelIterator};
use std::{time::Duration, borrow::Cow};
use std::{borrow::Cow, time::Duration};
use crate::fileinfo::FileInfo;
#[derive(Debug, Clone)]
pub enum State {
Initial,
SizeWise,
HashWise,
}
#[derive(Debug, Clone)]
pub struct Processor {
pub files: Vec<FileInfo>,
pub state: State,
pub hashwise_results: DashMap<String, Vec<FileInfo>>,
pub sizewise_results: DashMap<u64, Vec<FileInfo>>,
pub max_path_len: usize,
}
impl Processor {
pub fn new(files: Vec<FileInfo>) -> Self {
Self {
files,
state: State::Initial,
hashwise_results: DashMap::new(),
sizewise_results: DashMap::new(),
max_path_len: 0,
}
}
pub fn hashwise(&self) -> Result<Self> {
if self.files.is_empty() {
return Ok(self.clone());
pub fn hashwise(&mut self) -> Result<()> {
if self.sizewise_results.is_empty() {
return Ok(());
}
let progress_style = ProgressStyle::with_template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")?;
let progress_style = ProgressStyle::with_template(
"[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
)?;
let progress_bar = ProgressBar::new(self.files.len() as u64);
progress_bar.set_style(progress_style);
progress_bar.enable_steady_tick(Duration::from_millis(50));
progress_bar.set_message("indexing file hashes");
let duplicates_table: DashMap<String, Vec<FileInfo>> = DashMap::new();
self.files
let filelist = self
.sizewise_results
.clone()
.into_read_only()
.values()
.filter(|&subfiles| subfiles.len() > 1)
.flatten()
.cloned()
.collect::<Vec<FileInfo>>();
self.max_path_len = filelist
.iter()
.map(|x| x.path.clone().into_os_string().len())
.max()
.unwrap_or_default();
filelist
.into_par_iter()
.progress_with(progress_bar)
.with_finish(ProgressFinish::WithMessage(Cow::from("indexed files hashes")))
.with_finish(ProgressFinish::WithMessage(Cow::from(
"indexed files hashes",
)))
.map(|file| file.hash())
.filter_map(Result::ok)
.for_each(|file| {
duplicates_table
.for_each(move |file| {
self.hashwise_results
.entry(file.hash.clone().unwrap_or_default())
.and_modify(|fileset| fileset.push(file.clone()))
.or_insert_with(|| vec![file]);
});
let files = duplicates_table
.into_read_only()
.values()
.cloned()
.filter(|subfiles| subfiles.len() > 1)
.flatten()
.collect::<Vec<FileInfo>>();
Ok(Self {
files,
state: State::HashWise,
})
Ok(())
}
pub fn sizewise(&self) -> Result<Self> {
pub fn sizewise(&mut self) -> Result<()> {
if self.files.is_empty() {
return Ok(self.clone());
return Ok(());
}
let progress_style = ProgressStyle::with_template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")?;
let progress_style = ProgressStyle::with_template(
"[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
)?;
let progress_bar = ProgressBar::new(self.files.len() as u64);
progress_bar.set_style(progress_style);
progress_bar.enable_steady_tick(Duration::from_millis(50));
progress_bar.set_message("indexing file sizes");
let duplicates_table: DashMap<u64, Vec<FileInfo>> = DashMap::new();
self.files
.clone()
.into_par_iter()
.progress_with(progress_bar)
.with_finish(ProgressFinish::WithMessage(Cow::from("indexed files sizes")))
.with_finish(ProgressFinish::WithMessage(Cow::from(
"indexed files sizes",
)))
.for_each(|file| {
duplicates_table
self.sizewise_results
.entry(file.size)
.and_modify(|fileset| fileset.push(file.clone()))
.or_insert_with(|| vec![file]);
});
let files = duplicates_table
.into_read_only()
.values()
.cloned()
.filter(|subfiles| subfiles.len() > 1)
.flatten()
.collect::<Vec<FileInfo>>();
Ok(Self {
files,
state: State::SizeWise,
})
Ok(())
}
}