From 921c1b19c1b93fb53b0ebb0087a5d89909431991 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Wed, 17 Apr 2024 19:24:22 +0100 Subject: [PATCH] perf: check filesize first to reduce HashData alloc --- FindDuplicates/ListCommand.cs | 37 ++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/FindDuplicates/ListCommand.cs b/FindDuplicates/ListCommand.cs index ad2315f..9196c5d 100644 --- a/FindDuplicates/ListCommand.cs +++ b/FindDuplicates/ListCommand.cs @@ -8,6 +8,7 @@ namespace FindDuplicates; internal sealed class ListCommand : AsyncCommand { + private readonly ConcurrentDictionary> _fileSizeMap = new(); private readonly ConcurrentDictionary> _fileHashMap = new(); public override async Task ExecuteAsync(CommandContext context, ListSettings settings) @@ -95,9 +96,15 @@ internal sealed class ListCommand : AsyncCommand { foreach (FileInfo file in currentDirectory.EnumerateFiles()) { - string relativeFilePath = Path.GetRelativePath(inputDirectory.FullName, file.FullName); - AnsiConsole.MarkupLineInterpolated($"Checking hash for [cyan]{relativeFilePath}[/]"); - tasks.Add(Task.Run(() => ProcessFile(file, settings))); + try + { + ConcurrentBag cache = _fileSizeMap.GetOrAdd(file.Length, _ => []); + cache.Add(file); + } + catch (Exception ex) + { + AnsiConsole.MarkupLineInterpolated($"[red]Error:[/] {ex.Message}"); + } } } catch (Exception ex) @@ -105,6 +112,30 @@ internal sealed class ListCommand : AsyncCommand AnsiConsole.MarkupLineInterpolated($"[red]Error:[/] {ex.Message}"); } } + + foreach ((_, ConcurrentBag files) in _fileSizeMap) + { + if (files.Count < 1) + continue; + + tasks.Add(Task.Run(() => + { + foreach (FileInfo file in files) + { + try + { + AnsiConsole.MarkupLineInterpolated($"Checking hash for [cyan]{file.Name}[/]"); + ProcessFile(file, settings); + } + catch (Exception ex) + { + AnsiConsole.MarkupLineInterpolated($"[red]Error:[/] {ex.Message}"); + } + } + })); + } + + _fileSizeMap.Clear(); } private void ProcessFile(FileInfo file, ListSettings settings)