perf: Parallelverarbeitung wiederherstellen (2.4-2.9x Speedup)
rayon's par_iter() auf indexierten Collections bewahrt die Reihenfolge, daher war die Entfernung im vorherigen Commit unnötig. Mapping-Logik in Closure extrahiert um Code-Duplizierung zu vermeiden. Benchmark (dry-run, quiet): 5.050 Einträge: 48ms seq → 20ms par (2.4x) 20.050 Einträge: 186ms seq → 63ms par (2.9x) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ad44139e21
commit
b08ff38a49
1 changed files with 38 additions and 28 deletions
28
src/main.rs
28
src/main.rs
|
|
@ -11,6 +11,7 @@ use config::Config;
|
||||||
use glob::Pattern;
|
use glob::Pattern;
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
|
use rayon::prelude::*;
|
||||||
use sanitizer::{clean_filename, is_excluded, is_safe_rename, Sequence};
|
use sanitizer::{clean_filename, is_excluded, is_safe_rename, Sequence};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::IsTerminal;
|
use std::io::IsTerminal;
|
||||||
|
|
@ -31,6 +32,9 @@ const DEFAULT_EXCLUDES: &[&str] = &[
|
||||||
"__pycache__/**",
|
"__pycache__/**",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Schwellwert für parallele Verarbeitung (bei weniger Dateien lohnt sich der Overhead nicht)
|
||||||
|
const PARALLEL_THRESHOLD: usize = 100;
|
||||||
|
|
||||||
/// Repräsentiert eine geplante Umbenennungsoperation
|
/// Repräsentiert eine geplante Umbenennungsoperation
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct RenameOperation {
|
struct RenameOperation {
|
||||||
|
|
@ -161,12 +165,10 @@ fn main() -> Result<()> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Berechne Umbenennungen
|
// Berechne Umbenennungen (parallel bei vielen Dateien, sequentiell bei wenigen)
|
||||||
// Hinweis: Die Reihenfolge (tiefste zuerst) muss erhalten bleiben,
|
// Hinweis: rayon's par_iter() auf indexierten Collections bewahrt die Reihenfolge,
|
||||||
// damit Parent-Verzeichnisse nicht vor ihren Kindern umbenannt werden.
|
// sodass die tiefenbasierte Sortierung erhalten bleibt.
|
||||||
let rename_ops: Vec<RenameOperation> = entries
|
let map_entry = |entry: &walkdir::DirEntry| -> Option<RenameOperation> {
|
||||||
.iter()
|
|
||||||
.filter_map(|entry| {
|
|
||||||
let old_path = entry.path();
|
let old_path = entry.path();
|
||||||
|
|
||||||
// Ebenentiefe 0 -> überspringen
|
// Ebenentiefe 0 -> überspringen
|
||||||
|
|
@ -178,7 +180,10 @@ fn main() -> Result<()> {
|
||||||
let file_type = entry.file_type();
|
let file_type = entry.file_type();
|
||||||
if !args.special && (!file_type.is_file() && !file_type.is_dir()) {
|
if !args.special && (!file_type.is_file() && !file_type.is_dir()) {
|
||||||
if args.verbose && file_type.is_symlink() {
|
if args.verbose && file_type.is_symlink() {
|
||||||
debug!("Überspringe Symlink: {} (nutze --special um Symlink-Namen zu bereinigen)", old_path.display());
|
debug!(
|
||||||
|
"Überspringe Symlink: {} (nutze --special um Symlink-Namen zu bereinigen)",
|
||||||
|
old_path.display()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
@ -192,8 +197,13 @@ fn main() -> Result<()> {
|
||||||
old_path: old_path.to_path_buf(),
|
old_path: old_path.to_path_buf(),
|
||||||
new_path,
|
new_path,
|
||||||
})
|
})
|
||||||
})
|
};
|
||||||
.collect();
|
|
||||||
|
let rename_ops: Vec<RenameOperation> = if entries.len() >= PARALLEL_THRESHOLD {
|
||||||
|
entries.par_iter().filter_map(map_entry).collect()
|
||||||
|
} else {
|
||||||
|
entries.iter().filter_map(map_entry).collect()
|
||||||
|
};
|
||||||
|
|
||||||
// Statistiken
|
// Statistiken
|
||||||
let total_processed = entries.len();
|
let total_processed = entries.len();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue